ruby to_f 错误或乘法运算符错误?
您好,我刚刚遇到一个问题,Ruby 的 to_f
函数给我的结果不一致。
ruby-1.9.2-head :026 > 8.45.to_f * 100
=> 844.9999999999999
ruby-1.9.2-head :027 > 4.45.to_f * 100
=> 445.0
ruby-1.9.2-head :028 > 4.35.to_f * 100
=> 434.99999999999994
我的解决方法是简单地以这种方式对结果进行舍入
ruby-1.9.2-head :029 > (4.35.to_f * 100).round
=> 435
经过更多尝试后,我意识到问题可能出在乘法运算符 * 100
Hi I just ran into an issue where ruby's to_f
function is giving me inconsistent results.
ruby-1.9.2-head :026 > 8.45.to_f * 100
=> 844.9999999999999
ruby-1.9.2-head :027 > 4.45.to_f * 100
=> 445.0
ruby-1.9.2-head :028 > 4.35.to_f * 100
=> 434.99999999999994
My workaround is to simply round the result this way
ruby-1.9.2-head :029 > (4.35.to_f * 100).round
=> 435
After more playing around I realised that the issue might be with the multiplication operator * 100
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
欢迎来到浮点漂移。这是一个很好理解的问题,你应该读一读,这样你至少自己就能理解它。例如,请查看以下文章:
Welcome to floating point drift. This is a well understood problem, and you should have a read so you at least understand it yourself. For instance, have a peek over at the following article:
Float 的问题已经提到过。请参阅检查其他答案。
更多评论:
您编写了
4.35.to_f
。在这种情况下,to_f
不是必需的。4.35 已经是一个 Float:
你在哪里认识到问题的。当您打印数字时,该值已经四舍五入。
使用 String#% 您可以确定输出的详细级别:
The problems with Float are already mentioned. See check the other answers.
Some more remarks:
You wrote
4.35.to_f
. Theto_f
is not necessary in this case.4.35 is already a Float:
Where did you recognize the problem. When you print the number the value is already rounded.
With String#% you can determine the details level of the output:
唉,这是浮点数学诅咒的一部分,而不仅仅是 Ruby 中的问题:
http://en.wikipedia.org/wiki/Floating_point#Representable_numbers.2C_conversion_and_rounding
如果您需要精确的小数算术,请使用大十进制:
Alas, this is part of the curse of floating point math, and not just a problem in Ruby:
http://en.wikipedia.org/wiki/Floating_point#Representable_numbers.2C_conversion_and_rounding
If you need exact arithmetic with decimals, use BigDecimal:
根本问题是分数 45/100 没有精确表示为 1/2n 项的序列。事实上,大多数用少量 10 进制数字书写的分数没有精确的 FP 表示。
因此,您得到的实际数字与 10 进制数字非常接近,但并不精确。输出结果将取决于您舍入的位置,但如果您在舍入时做了任何最合理的事情,那么输出结果将是正确的。
如果不四舍五入,您得到的确切数字将取决于分数被截断的位置以及您尝试转换的位数。分数被截断的位置取决于需要多少位来表示尾数。这就是为什么您会根据 x 得到不同的 x.45 结果。
这个问题在堆栈溢出时总是出现。我想我们需要一个浮点常见问题解答。
讽刺的是,每个(在范围内)整数值都具有精确的浮点格式表示。
The fundamental problem is that the fraction 45/100 does not have an exact representation as a sequence of 1/2n terms. In fact, most fractions written with a small number of base-10 digits do not have an exact FP representation.
As a result, the actual number you get is a very close but not exact approximation to your base-10 number. The output results will depend on where you round to, but will be correct if you do anything the least bit reasonable when rounding.
If you don't round, the exact number you get will depend on where the fraction gets chopped off and on how many digits you attempt to convert. Where the fraction is chopped will depend on how many bits are needed to represent the mantissa. That's why you get different results for x.45 depending on x.
This question comes up all the time on stack overflow. I guess we need a floating-point-faq.
Ironically, every (in range) integer value does have an exact floating point format representation.