Class: BigDecimal

Inherits:
Object
  • Object
show all
Includes:
Nio::Formattable
Defined in:
lib/nio/fmt.rb,
lib/nio/rtnlzr.rb,
lib/nio/rtnlzr.rb

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Nio::Formattable

append_features, #nio_round, #nio_write

Class Method Details

.nio_read_neutral(neutral) ⇒ Object



1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
# File 'lib/nio/fmt.rb', line 1797

def self.nio_read_neutral(neutral)   
  x = nil
  
  if neutral.special?
    case neutral.special
      when :nan
        x = BigDecimal('NaN') # BigDecimal("0")/0
      when :inf
        x = BigDecimal(neutral.sign=='-' ? '-1.0' : '+1.0')/0
    end
  elsif neutral.rep_pos<neutral.digits.length  
    
    x,y = neutral.to_RepDec.getQ
    x = BigDecimal(x.to_s)/y
    
  else
    if neutral.base==10
      #x = BigDecimal(neutral.digits)
      #x *= BigDecimal("1E#{(neutral.dec_pos-neutral.digits.length)}")
      #x = -x if neutral.sign=='-'
      str = neutral.sign
      str += neutral.digits
      str += "E#{(neutral.dec_pos-neutral.digits.length)}"
      x = BigDecimal(str)
    else
      x = BigDecimal(neutral.digits.to_i(neutral.base).to_s)    
      x *= BigDecimal(neutral.base.to_s)**(neutral.dec_pos-neutral.digits.length)
      x = -x if neutral.sign=='-'
    end
  end
   
  return x
end

Instance Method Details

#nio_r(tol = nil) ⇒ Object

Conversion to Rational. The optional argument must be one of:

  • a Nio::BigTolerance that defines the admisible tolerance; in that case, the smallest denominator rational within the tolerance will be found (which may take a long time for small tolerances.)

  • an integer that defines a maximum value for the denominator. in which case, the best approximation with that maximum denominator will be returned.



129
130
131
132
133
134
135
136
137
# File 'lib/nio/rtnlzr.rb', line 129

def nio_r(tol = nil)
  tol ||= BigTolerance.decimals([precs[0],Float::DIG].max,:sig)
  case tol
    when Integer
      Rational(*Nio::Rtnlzr.max_denominator(self,tol,BigDecimal))
    else
      Rational(*Nio::Rtnlzr.new(Nio::BigTol(tol)).rationalize(self))
  end
end

#nio_write_neutral(fmt) ⇒ Object



1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
# File 'lib/nio/fmt.rb', line 1830

def nio_write_neutral(fmt)
  neutral = Nio::NeutralNum.new
  x = self
  
  if x.nan?
    neutral.set_special(:nan)
  elsif x.infinite?
    neutral.set_special(:inf, x<0 ? '-' : '+')
  else  
    converted = false
    if fmt.get_ndig==:exact && fmt.get_approx==:simplify
      
      prc = [x.precs[0],20].max
      neutral = x.nio_r(Nio::BigTolerance.decimals(prc,:sig)).nio_write_neutral(fmt)
      converted = true if neutral.digits.length<prc
      
    elsif fmt.get_approx==:exact && fmt.get_base!=10
      neutral = x.nio_xr.nio_write_neutral(fmt)
      converted = true
    end
    if !converted 
      if fmt.get_base==10 
        txt = x.to_s
        
        sign = '+'    
        if txt[0,1]=='-'
          sign = '-'
          txt = txt[1...txt.length]
        end
        exp = 0
        x_char = fmt.get_exp_char(fmt.get_base)

        exp_i = txt.index(x_char)
        exp_i = txt.index(x_char.downcase) if exp_i===nil
        if exp_i!=nil
          exp = txt[exp_i+1...txt.length].to_i
          txt = txt[0...exp_i] 
        end    
        
        dec_pos = txt.index '.'
        if dec_pos==nil
          dec_pos = txt.length 
        else
          txt[dec_pos]=''
        end
        dec_pos += exp
        neutral.set sign, txt, dec_pos, nil, fmt.get_base_digits(10), true, fmt.get_round
        
        converted = true
      end
    end  
    if !converted
      
      min_prec = 24
      min_exp  = -1000
      s,f,b,e = x.split
      e -= f.size
      sign = s<0 ? '-' : '+'
      x = -x if sign=='-'
      f_i = f.to_i
      prc = [x.precs[0],min_prec].max
      f_i *= 10**(prc-f.size)
      e -= (prc-f.size)

      inexact = true

      rounding = fmt.get_round
      
      if fmt.get_all_digits?
        # use as many digits as possible
        dec_pos,r,*digits = Nio::BurgerDybvig::float_to_digits_max(x,f_i,e,rounding,[e,min_exp].min,prc,b,fmt.get_base)
        inexact = :roundup if r
      else
        # use as few digits as possible
        dec_pos,*digits = Nio::BurgerDybvig::float_to_digits(x,f_i,e,rounding,[e,min_exp].min,prc,b,fmt.get_base)
      end
      txt = ''
      digits.each{|d| txt << fmt.get_base_digits.digit_char(d)}
      neutral.set sign, txt, dec_pos, nil, fmt.get_base_digits, inexact, fmt.get_round
      
    end
  end
       
  return neutral
end

#nio_xrObject

Conversion to Rational preserving the exact value of the number.



67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/nio/rtnlzr.rb', line 67

def nio_xr
  s,f,b,e = split
  p = f.to_i
  p = -p if s<0
  e = f.size-e
  if e<0
    p *= b**(-e)
    e = 0
  end
  q = b**(e)
  return Rational(p,q)
end