红宝石精确数字对数(对数)函数

时间:2019-05-29 22:01:54

标签: ruby logarithm

由于以10为底的10对数为3,因此您可能期望Math::log(1000, 10)返回3。而是返回2.9999999999999996

这是由于事实,例如here中所讨论的,Ruby中的浮点数不是精确数字:

  

浮点数不是精确的数字表示形式,如ruby docs中所述:

     
    

浮点对象使用本机体系结构的双精度浮点表示形式表示不精确的实数。

  
     

这不是红宝石故障,因为浮子只能由固定的代表   字节数,因此无法正确存储十进制数。

     

或者,您可以使用ruby RationalBigDecimal

不幸的是,调用Math::log(BigDecimal('1000'), BigDecimal('10'))时结果完全相同。 Math::log(Rational('1000'), Rational('10'))也是如此。还有一个does something completely differentBigMath::log

现在最大的问题是:如何计算以10为底的10对数,以便获得准确的结果:3

2 个答案:

答案 0 :(得分:0)

您可以使用change of base formula:如果您可以使用底数d计算日志,但是您需要底数b,然后是log_b(n) = log_d(n) / log_d(b)。所以:

> BigMath.log(1000, 50) / BigMath.log(10, 50)
=> 0.3e1

现在让我们尝试一些需要更高精度的东西:

> BigMath.log(999, 50) / BigMath.log(10, 50)
=> 0.2999565488225982308693534399304475375583359282738400141107276831709276456467950527020061473296516829369378125e1

https://www.wolframalpha.com/input/?i=log_10+999

进行比较

答案 1 :(得分:0)

您在这里遇到了浮点数的限制。 Floats typically have a precision of 15 decimal places in Ruby,但值2.9999999999999996显示16位小数位(不可靠)的精度。

要恢复到可靠的精度,请四舍五入到小数点后15位:

>> Math::log(1000, 10)
=> 2.9999999999999996
>> Math::log(1000, 10).round(15)
=> 3.0

double的C语言规范only requires 10 significant decimal places,因此Ruby实现可能有Float的有效小数位数少于15个,但仍然更多常见的是在这里看到15个有效的小数位。