设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