4

Rational有限の 10 進数表現を持つ任意の大きな (または小さな)数値を指定すると、次のようになります。

r = Rational(1, 2**15)
#=> (1/32768)

完全な 10 進数値を文字列として取得するにはどうすればよいですか?

上記の数値の予想される出力は次のとおりです。

"0.000030517578125"

to_fどうやらうまくいかない:

r.to_f
#=> 3.0517578125e-05

sprintf数を指定する必要があります。

sprintf('%.30f', r)
#=> "0.000030517578125000000000000000"
4

3 に答える 3

1

ほとんどの 10 歳児はその方法を知っています: 長い割り算を使用してください! 1

コード

def finite_long_division(n,d)
  return nil if d.zero?
  sign = n*d >= 0 ? '' : '-'
  n, d = n.abs, d.abs
  pwr =
  case n <=> d
  when 1 then power(n,d)
  when 0 then 0
  else        -power(d,n)-1
  end            
  n *= 10**(-pwr) if pwr < 0
  d *= 10**(pwr)  if pwr >= 0
  s = ld(n,d)
  t = s.size == 1 ? '0' : s[1..-1]
  "%s%s.%s x 10^%d" % [sign, s[0], t, pwr]
end

def power(n, d)
  # n > d
  ns = n.to_s
  ds = d.to_s
  pwr = ns.size - ds.size - 1
  pwr += 1 if ns[0, ds.size].to_i >= ds.to_i
  pwr
end

def ld(n,d)
  s = ''
  loop do # .with_object('') do |s|
    m,n = n.divmod(d)
    s << m.to_s
    return s if n.zero?
    n *= 10
  end
end

2

finite_long_division(1, 2**15)
  #=> "3.0517578125 x 10^-5"
finite_long_division(-1, 2**15)
  #=> "-3.0517578125 x 10^-5"
finite_long_division(-1, -2**15)
  #=> "3.0517578125 x 10^-5"

finite_long_division(143, 16777216)
  #=> "8.523464202880859375 x 10^-6"
143/16777216.0
  #=> 8.52346420288086e-06 

finite_long_division(8671,
  803469022129495137770981046170581301261101496891396417650688)
  #=> "1.079195309486679194852923588206549145803161531099624\
  #      804222395643336829571798416196370119711226461255452\
  #      67714596064934085006825625896453857421875 x 10^-56"      

すべての有理数には 10 進表現があるか、無限に繰り返される一連の数字 (たとえば、1/3 #=> 0.33333...3227/555 #=> 5.8144144144...3 1/9967 #=> 0.00010033109260559848...)が含まれていることを思い出してください。したがって、このメソッドは、有理数が反復シーケンスの種類である場合、決して終了しません。一般に、有理数がどのタイプであるかを事前に知ることはできないため、有理数が有限の 10 進数表現を持っているかどうかを最初に判断するようにメソッドを変更すると便利な場合があります。(共通因数を取り除くことによって) 減数できない有理数は、 で割り切れ、他の素数では割り切れないn/d場合にのみ、この性質を持つことが知られています。4d25すでに簡約された有理数がその特性を持っているかどうかを判断する方法を簡単に構築できます。

require 'prime'

def decimal_representation?(n, d)
  primes = Prime.prime_division(d).map(&:first)
  (primes & [2,5]).any? && (primes - [2, 5]).empty?
end

1 少なくとも私が子供の頃はそうでした。

2有限の 10 進数表現を持つ有理数の部分的なリストについては、こちらを参照してください。

3 この有理数の繰り返しシーケンスには 9,966 桁が含まれます。

4参照

于 2016-12-21T03:29:16.603 に答える
1

Bigdecimalto_sには "F" オプションがあります。ただし、この合理性を形にするためには、ある程度の変換が必要です。

require "bigdecimal"
r = Rational(1, 2**15)
p   BigDecimal.new(r.to_f.to_s).to_s("F") # => "0.000030517578125"
于 2016-11-25T21:38:59.610 に答える