计算最接近首选十进制结果的双精度值



设N(x)为有效位数最少的十进制数的值使得x是最接近该数值的double值。

给定double值a和b, 如何计算最接近N(b)-N(a)的double值?

例如:

  • 如果a和b是最接近0.2和0.3的double值,
    • 期望的结果是double值最接近于。1,
        0.1000000000000000055511151231257827021181583404541015625
      • ,
    • 而不是直接减去a和b的结果,
        0.09999999999999997779553950749686919152736663818359375

作为基线:在Java中,Double.toString()提供问题中描述的N(x)函数,以数字形式返回其值。可以取a和b的字符串,用小学方法减去它们,然后将结果字符串转换为double

这表明使用现有的库例程解决问题是非常可行的。这就留下了改进解决方案的任务。我建议探索:

  • 是否有一个函数D(x)返回N(x)中描述的数字的小数点后的有效位数?如果是这样,我们可以将a和b乘以由D(a)和D(b)决定的10次方,根据需要四舍五入以产生正确的整数结果(对于它们可以表示为double值的情况),减去它们,然后除以10的幂吗?
  • 我们是否可以建立一个标准,使b-a或一些简单的表达式可以快速四舍五入到接近十进制的数字,绕过对更困难的情况所必需的代码?例如,我们能否证明对于一定范围内的数字,(round(10000*b)-round(10000*a))/10000总是产生期望的结果?

您可以通过乘以然后除以10的幂来转换为'整数':

(10*.3 - 10*.2)/10 == 0.1000000000000000055511151231257827021181583404541015625

也许可以从该数的字符串表示中计算出相应的10的幂。@ patricia ashanahan建议寻找重复的0或9。

考虑使用BigDecimal库,如javascript-bignum。

您也可以在Smalltalk Pharo 2.0中查询您的请求翻译:

^(b asMinimalDecimalFraction - a asMinimalDecimalFraction) asFloat

代码可以在code.google.com/p/pharo/issues上找到问题4957的附件-唉,死链接,新的错误跟踪器需要登录…

https://pharo.fogbugz.com/f/cases/5000/Let-asScaledDecimal-use-the-right-number-of-decimals

源代码也在github上,目前:

https://github.com/pharo-project/pharo-core/blob/6.0/Kernel.package/Float.class/instance/printing/asMinimalDecimalFraction.st

算法基于:

Robert G. Burger和R. Kent Dybvig
快速准确地打印浮点数
ACM SIGPLAN 1996编程语言设计与实现会议
1996年6月。
http://www.cs.indiana.edu/dyb/酒吧/FP-Printing-PLDI96.pdf

最新更新