如何将有理数格式化为小数? [英] How to format a Rational number as a decimal?

查看:210
本文介绍了如何将有理数格式化为小数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给出具有有限小数表示形式的任意大(或小)Rational数字,例如:

Given an arbitrary large (or small) Rational number that has a finite decimal representation, e.g.:

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

如何获取完整的十进制值作为字符串?

How can I get its full decimal value as a string?

上述数字的预期输出为:

The expected output for the above number is:

"0.000030517578125"

to_f显然不起作用:

r.to_f
#=> 3.0517578125e-05

sprintf要求我指定位数:

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

推荐答案

大多数十岁的孩子都知道该怎么做:使用长除法! 1

Most ten-year-olds know how to do that: use long division!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"      

回想一下,每个有理数都用十进制表示或包含无限重复的数字序列(例如1/3 #=> 0.33333...3227/555 #=> 5.8144144144...1/9967 #=> 0.00010033109260559848... 3 ).因此,如果有理数具有重复序列的多样性,则该方法将永远不会终止.由于通常通常不知道有理数是哪种类型,因此修改该方法以首先确定有理数是否具有有限的十进制表示形式可能会很有用.已知只有且仅当d可被25整除且不能被任何其他素数整除时,无法减少(通过除去公因子)的有理数n/d具有此属性. . 4 我们可以轻松地构造一种方法来确定已经减少的有理数是否具有该性质.

Recall that every rational number has either a decimal representation or contains an infinitely-repeating sequence of digits (e.g., 1/3 #=> 0.33333..., 3227/555 #=> 5.8144144144... and 1/9967 #=> 0.00010033109260559848...3). This method would therefore never terminate if the rational was of the repeating sequence variety. Since one generally doesn't know in advance which type a rational number is, it might be useful to modify the method to first determine if the rational number has a finite decimal representation. It is known that a rational number n/d which cannot be reduced (by removing common factors) has this property if and only if d is divisible by 2 or by 5 and is not divisible by any other prime number.4 We could easily construct a method to determine if an already-reduced rational number has that property.

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请参见

2 See here for a partial list of rational numbers that have finite decimal representations.

3该有理数的重复序列包含9,966个数字.

4 参考 .

这篇关于如何将有理数格式化为小数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆