BigDecimal(�•ϒ����������_���Z�p�g�����C�u����)

English

BigDecimal �̓I�u�W�F�N�g�w���̋��͂ȃX�N���v�g����ł��� Ruby �ɉ•ϒ����������_ �v�Z�@�\��lj����邽�߂̊g�����C�u�����ł��B Ruby �ɂ‚��Ă̏ڂ������e�͈ȉ���URL���Q�Ƃ��Ă��������B

�ڎ�


�͂��߂�

Ruby �ɂ� Bignum �Ƃ����N���X������A���S���̐����ł��v�Z���邱�Ƃ��ł��܂��B �����A�C�ӌ��̕��������_���Z�p�N���X�������悤�ł��B�����ŁA �C�ӌ��̕��������_���Z�p�g�����C�u���� BigDecimal ���쐬���܂����B �s��⏕���E��Ă�����ꍇ�ǂ��ǂ��A
shigeo@tinyforest.gr.jp �܂ł��m�点���������B�s��𒼂��C�͑傢�ɂ���܂��B�����A���ԂȂǂ̊֌W�Ŗ� �͂ł��܂���B�܂��A���ʂɂ‚��Ă��ۏ؂ł�����̂ł͂���܂���B �\�߁A���������������B

���̃v���O�����́A���R�ɔz�z�E���ς��č\���܂���B�������A���쌠�͕������Ă��܂���B �z�z�E���ϓ��̌����� Ruby �̂���ɏ����܂��B�ڂ����� README ��ǂ�ł��������B

�C���X�g�[���ɂ‚���

BigDecimal ���܂� Ruby �̍ŐV�ł�Ruby�����y�[�W����_�E�����[�h�ł��܂��B �_�E�����[�h�����ŐV�ł��𓀂�����A�ʏ�̃C���X�g�[���菇�����s���ĉ������B Ruby ���������C���X�g�[�������΁A������ BigDecimal �����p�ł���悤�ɂȂ�͂��ł��B �\�[�X�t�@�C���� bigdecimal.c,bigdecimal.h �̂Q�‚݂̂ł��B

�g�p���@�ƃ��\�b�h�̈ꗗ

�uRuby�͊��ɏ�����v�Ƃ����O��ŁA
require 'bigdecimal'
a=BigDecimal::new("0.123456789123456789")
b=BigDecimal("123456.78912345678",40)
c=a+b

�Ƃ����悤�Ȋ����Ŏg�p���܂��B

���\�b�h�ꗗ

�ȉ��̃��\�b�h�����p�”\�ł��B �u�L�������v�Ƃ� BigDecimal �����x��ۏ؂��錅���ł��B �҂�����ł͂���܂���A�኱�̗]�T�������Čv�Z����܂��B �܂��A�Ⴆ�΂R�Q�r�b�g�̃V�X�e���ł͂P�O�i�łS�����Ɍv�Z���܂��B�]���āA����ł́A �����́u�L�������v�͂S�̔{���ƂȂ��Ă��܂��B

�ȉ��̃��\�b�h�ȊO�ɂ��A(C �ł͂Ȃ�) Ruby �\�[�X�̌`�� �񋟂���Ă�����̂�����܂��B�Ⴆ�΁A

require "bigdecimal/math.rb"
�Ƃ��邱�ƂŁAsin �� cos �Ƃ������֐����g�p�ł���悤�ɂȂ�܂��B �g�p���@�ȂǁA�ڍׂ� math.rb �̓��e���Q�Ƃ��ĉ������B ���̑��AFloat �Ƃ̑��ݕϊ��Ȃǂ̃��\�b�h�� util.rb �ŃT�|�[�g����Ă��܂��B ���p����ɂ�
require "bigdecimal/util.rb"
�̂悤�ɂ��܂��B�ڍׂ� util.rb �̓��e���Q�Ƃ��ĉ������B

�N���X���\�b�h

�C���X�^���X���\�b�h

��́A�ǂ�Ŏ��̔@���ł��B

coerce�ɂ‚���

BigDecimal �I�u�W�F�N�g���Z�p���Z�q�̍��ɂ���Ƃ��́ABigDecimal �I�u�W�F�N�g�� �E�ɂ���I�u�W�F�N�g��(�K�v�Ȃ�) BigDecimal �ɕϊ����Ă���v�Z���܂��B �]���āABigDecimal �I�u�W�F�N�g�ȊO�ł����l���Ӗ�������̂Ȃ�E�ɒu���� ���Z�͉”\�ł��B
�������A������́i�ʏ�j���l�Ɏ����ϊ����邱�Ƃ͂ł��܂���B ������𐔒l�Ɏ����ϊ��������ꍇ�� bigfloat.c �� �u/* #define ENABLE_NUMERIC_STRING */�v�̃R�����g���O���Ă���A �ăR���p�C���A�ăC���X�g�[������K�v������܂��B ������Ő��l��^����ꍇ�͒��ӂ��K�v�ł��B���l�ɕϊ��ł��Ȃ�����������ƁA �P�ɕϊ����~�߂邾���ŃG���[�ɂ͂Ȃ�܂���B"10XX"�Ȃ�P�O�A"XXXX"�͂O �ƈ����܂��B
   a = BigDecimal.E(20)
   c = a * "0.123456789123456789123456789" # ������ BigDecimal �ɕϊ����Ă���v�Z
�������񐔂�\�������Ƃ��āA"Infinity"�A"+Infinity"�A"-Infinity"�A"NaN" ���g�p�ł��܂�(�啶���E����������ʂ��܂�)�B�������Amode ���\�b�h�� false �� �w�肵���ꍇ�͗�O���������܂��B
�܂��ABigDecimal�N���X�� coerce�iRuby�{�Q�Ɓj���T�|�[�g���Ă��܂��B �]���āABigDecimal �I�u�W�F�N�g���E�ɂ���ꍇ�����͑��v�ł��B �����A���݂� Ruby �C���^�v���^�̎d�l��A�����񂪍��ɂ���ƌv�Z�ł��܂���B
  a = BigDecimal.E(20)
  c = "0.123456789123456789123456789" * a # �G���[
�K�v��������Ƃ͎v���܂��񂪁A�ǂ����Ă��ƌ����l�� String �I�u�W�F�N�g���p�������V���ȃN���X���쐬���Ă���A ���̃N���X�� coerce ���T�|�[�g���Ă��������B

�����A�񐔁A�[���̈���

�u�����v�Ƃ͕\���ł��Ȃ����炢�傫�Ȑ��ł��B���ʂɈ������߂� +Infinity�i���̖�����j�� -Infinity�i���̖�����j�Ƃ��� �悤�ɕ\�L����܂��B ������ 1.0/0.0 �̂悤�Ƀ[���Ŋ���悤�Ȍv�Z�������Ƃ��ɐ�������܂��B

�u�񐔁v�� 0.0/0.0 �� Infinity-Infinity ���̌��ʂ���`�ł��Ȃ� �v�Z�������Ƃ��ɐ�������܂��B�񐔂� NaN�iNot a Number�j�ƕ\�L����܂��B NaN ���܂ތv�Z�͑S�� NaN �ɂȂ�܂��B�܂� NaN �͎������܂߂āA�ǂ�Ȑ� �Ƃ���v���܂���B

�[���� +0.0 �� -0.0 �����݂��܂��B�������A+0.0==-0.0 �� true �ł��B

Infinity�ANaN�A +0.0 �� -0.0 �����܂񂾌v�Z���ʂ͑g�ݍ��킹�� ��蕡�G�ł��B�����̂���l�́A�ȉ��̃v���O���������s���Č��ʂ� �m�F���Ă��������i���ʂɂ‚��āA�^���ԈႢ�𔭌����ꂽ���� ���m�点�肢�܂��j�B

require "bigdecimal"

aa  = %w(1 -1 +0.0 -0.0 +Infinity -Infinity NaN)
ba  = %w(1 -1 +0.0 -0.0 +Infinity -Infinity NaN)
opa = %w(+ - * / <=> > >=  < == != <=)

for a in aa
  for b in ba
    for op in opa
      x = BigDecimal::new(a)
      y = BigDecimal::new(b)
      eval("ans= x #{op} y;print a,' ',op,' ',b,' ==> ',ans.to_s,\"\n\"")
    end
  end
end


�����\��

BigDecimal�����ŕ��������_�͍\����(Real)�ŕ\������܂��B ���̂����������� unsigned long �̔z��(�ȉ��̍\���̗v�ffrac)�ŊǗ�����܂��B �T�O�I�ɂ́A�ȉ��̂悤�ɂȂ�܂��B

<���������_��> = 0.xxxxxxxxx*BASE**n

�����ŁAx�͉�������\�������ABASE�͊�i�P�O�i�Ȃ�P�O�j�An�͎w������\�� �����l�ł��BBASE���傫���قǁA�傫�Ȑ��l���\���ł��܂��B�‚܂�A�z��̃T�C�Y�� ���Ȃ��ł��܂��BBASE�͑傫���قǓs�����悢�킯�ł����A�f�o�b�O�̂��₷���Ȃǂ� �l�����āA10000�ɂȂ��Ă��܂��iBASE��VpInit()�֐��Ŏ����I�Ɍv�Z���܂��j�B ����́A32�r�b�g�����̏ꍇ�ł��B64�r�b�g�����̏ꍇ�͂����Ƒ傫�Ȓl�ɂȂ�܂��B �c�O�Ȃ���A64�r�b�g�����ł̃e�X�g�͂܂�����Ă��܂���i�����A���ꂽ��������� ���ʂ������Ă���������΂��肪�����ł��j�B BASE��10000�̂Ƃ��́A�ȉ��̉������̔z��(frac)�̊e�v�f�ɂ͍ő�łS���� �������i�[����܂��B

���������_�\����(Real)�͈ȉ��̂悤�ɂȂ��Ă��܂��B
  typedef struct {
     unsigned long MaxPrec; // �ő吸�x(frac[]�̔z��T�C�Y)
     unsigned long Prec;    // ���x(frac[]�̎g�p�T�C�Y)
     short    sign;         // �ȉ��̂悤�ɕ������̏�Ԃ��`���܂��B
                            //  ==0 : NaN
                            //    1 : +0
                            //   -1 : -0
                            //    2 : ���̒l
                            //   -2 : ���̒l
                            //    3 : +Infinity
                            //   -3 : -Infinity
     unsigned short flag;   // �e��̐���t���b�O
     int      exponent;     // �w�����̒l(������*BASE**exponent)
     unsigned long frac[1]; // �������̔z��(�•�)
  } Real;
�Ⴆ�� 1234.56784321 �Ƃ���������(BASE=10000�Ȃ�)
    0.1234 5678 4321*(10000)**1
�ł����� frac[0]=1234�Afrac[1]=5678�Afrac[2]=4321�A Prec=3�Asign=2�Aexponent=1 �ƂȂ�܂��BMaxPrec�� Prec ���傫����΂����‚ł����܂��܂���Bflag �� �g�p���@�͎����Ɉˑ����ē����Ŏg�p����܂��B

2�i��10�i

BigDecimal �� <���������_��> = 0.xxxxxxxxx*10**n �Ƃ���10�i�`���Ő��l��ێ����܂��B �������A�v�Z�@�̕��������_���̓����\���́A�����܂ł��Ȃ� <���������_��> = 0.bbbbbbbb*2**n �Ƃ��� 2�i�`�������ʂł�(x �� 0 ���� 9 �܂ŁAb �� 0 �� 1 �̐���)�B BigDecimal ���Ȃ�10�i�̓����\���`�����̗p�����̂����ȉ��ɐ������܂��B

10�i�̃����b�g

�f�o�b�O�̂��₷��
�܂��A�v���O�����쐬���y�ł��Bfrac[0]=1234�Afrac[1]=5678�Afrac[2]=4321�A exponent=1�Asign=2 �Ȃ琔�l�� 1234.56784321 �ł���̂͌���Β����ɕ�����܂��B
10�i�\�L���ꂽ���l�Ȃ�m���ɓ����\���ɕϊ��ł���
�Ⴆ�΁A�ȉ��̂悤�ȃv���O�����͑S���덷������ �v�Z���邱�Ƃ��ł��܂��B�ȉ��̗�́A��s�Ɉ�‚̐��l �������Ă���t�@�C�� file �̍��v���l�����߂���̂ł��B
   file = File::open(....,"r")
   s = BigDecimal::new("0")
   while line = file.gets
      s = s + line
   end
���̗��2�i���ł��ƌ덷�����荞�މ”\��������܂��B �Ⴆ�� 0.1 ��2�i�ŕ\������� 0.1 = b1*2**(-1)+b1*2**(-2)+b3*2**(-3)+b4*2**(-4).... �Ɩ����ɑ����Ă��܂��܂�(b1=0,b2=0,b3=0,b4=1...)�B������ bn(n=1,2,3,...) �� 2�i��\������ 0 �� 1 �̐�����ł��B�]���āA�ǂ����őł��؂�K�v������܂��B �����ŕϊ��덷������܂��B�������A������ēx10�i�\�L�ɂ��Ĉ������悤�� �ꍇ�͓K�؂Ȋۂߑ���i�l�̌ܓ��j�ɂ���čĂ� "0.1" �ƕ\������܂��B�������A �����ł͐��m�� 0.1 �ł͂���܂���B
�L�������͗L���ł���i�‚܂莩������ł���j
0.1 ��\�����邽�߂̗̈�͂�������‚̔z��v�f�i frac[0]=1 �j�ōς݂܂��B �z��v�f�̐���10�i���l���玩���I�Ɍ���ł��܂��B����́A�•ϒ����������_���Z�ł� �厖�Ȃ��Ƃł��B�t�� 0.1 ��2�i�\�������Ƃ��ɂ�2�i�̗L�����������‚ɂ���̂� 0.1 �� ���������ł͌���ł��܂���B

10�i�̃f�����b�g

���͍��܂ł̃����b�g�́A���̂܂܃f�����b�g�ɂ��Ȃ�܂��B ���������A10�i��2�i�ɕϊ�����悤�ȑ���͕ϊ��덷 �𔺂��ꍇ��������邱�Ƃ͂ł��܂���B ��T�̃R���s���[�^��10�i�̓����\���������Ă��Ȃ��̂ŁA BigDecimal �𗘗p���Č덷�����̌v�Z������ꍇ�́A�v�Z���x �𖳎����Ă��Ō�܂� BigDecimal ���g�p������K�v������܂��B

�ŏ��͉����H

�����Ōv�Z����Ƃ��ɂ킴�킴2�i�����g���l�͋ɂ߂Ă܂�ł��B �v�Z�@�Ƀf�[�^����͂���Ƃ����قƂ�ǂ̏ꍇ�A 10�i���œ��͂��܂��B���̌��ʁAdouble ���̌v�Z�@���� �\���͍ŏ�����덷�������Ă���ꍇ������܂��B BigDecimal �̓��[�U���͂��덷�����Ŏ�荞�ނ��Ƃ��ł��܂��B �f�o�b�O�����₷���̂ƁA�f�[�^�ǂ݂��ݎ��Ɍ덷������Ȃ� �Ƃ����̂����ۂ̃����b�g�ł��B

�v�Z���x�ɂ‚���

c = a op b �Ƃ����v�Z(op �� + - * /)�������Ƃ��̓���� �ȉ��̂悤�ɂȂ�܂��B

�P�D��Z��(a �̗L������)+(b �̗L������)�A ���Z��(a �̍ő�L������)+(b �̍ő�L������)���̍ő包���i���ۂ́A�]�T�������āA ���������傫���Ȃ�܂��j�����•ϐ� c ��V���ɐ������܂��B �����Z�̏ꍇ�́A�덷���o�Ȃ������̐��x������ c �𐶐����܂��B�Ⴆ�� c = 0.1+0.1*10**(-100) �̂悤�ȏꍇ�Ac �̐��x�͂P�O�O���ȏ�̐��x�� ���‚悤�ɂȂ�܂��B

�Q�D���� c = a op b �̌v�Z�����s���܂��B

���̂悤�ɁA�����Z�Ə�Z�ł� c �͕K���u�덷���o�Ȃ��v�����̐��x�� �����Đ�������܂�(BigDecimal.limit ���w�肵�Ȃ��ꍇ)�B ���Z��(a �̍ő�L������)+(b �̍ő�L������)���̍ő包�� ������ c ����������܂����Ac = 1.0/3.0 �̂悤�Ȍv�Z�Ŗ��炩�Ȃ悤�ɁA c �̍ő吸�x�𒴂���Ƃ���Ōv�Z���ł��؂���ꍇ������܂��B

������ɂ���Ac �̍ő吸�x�� a �� b ���傫���Ȃ�܂��̂� c ���K�v�Ƃ��� �������[�̈�͑傫���Ȃ邱�Ƃɒ��ӂ��ĉ������B

���ӁF�u+,-,*,/�v�ł͌��ʂ̐��x�i�L�������j�������Ŏw��ł��܂���B ���x���R���g���[���������ꍇ�́A�ȉ��̃C���X�^���X���\�b�h���g�p���܂��B

�����Ő��x���R���g���[���������ꍇ

�����Ő��x(�L������)���R���g���[���������ꍇ�� add�Asub�Amult�Adiv ���̃��\�b�h ���g�p�ł��܂��B �ȉ��̉~�������v�Z����v���O������̂悤�ɁA ���߂錅���͎����Ŏw�肷�邱�Ƃ��ł��܂��B

#!/usr/local/bin/ruby

require "bigdecimal"
#
# Calculates 3.1415.... (the number of times that a circle's diameter
# will fit around the circle) using J. Machin's formula.
#
def big_pi(sig) # sig: Number of significant figures
  exp    = -sig
  pi     = BigDecimal::new("0")
  two    = BigDecimal::new("2")
  m25    = BigDecimal::new("-0.04")
  m57121 = BigDecimal::new("-57121")

  u = BigDecimal::new("1")
  k = BigDecimal::new("1")
  w = BigDecimal::new("1")
  t = BigDecimal::new("-80")
  while (u.nonzero? && u.exponent >= exp) 
    t   = t*m25
    u   = t.div(k,sig)
    pi  = pi + u
    k   = k+two
  end

  u = BigDecimal::new("1")
  k = BigDecimal::new("1")
  w = BigDecimal::new("1")
  t = BigDecimal::new("956")
  while (u.nonzero? && u.exponent >= exp )
    t   = t.div(m57121,sig)
    u   = t.div(k,sig)
    pi  = pi + u
    k   = k+two
  end
  pi
end

if $0 == __FILE__
  if ARGV.size == 1
    print "PI("+ARGV[0]+"):\n"
    p big_pi(ARGV[0].to_i)
  else
    print "TRY: ruby pi.rb 1000 \n"
  end
end


���� �ΗY (E-Mail:<shigeo@tinyforest.gr.jp>)