红宝石从23 + 9.23 = 32.230000000000004
看似不稳定的结果我收到了非常有趣的,看起来不稳定的Ruby结果。到底是怎么回事?红宝石从23 + 9.23 = 32.230000000000004
这是正确的!
>> 23+9.22
=> 32.22
这不是!
>> 23+9.23
=> 32.230000000000004
所有尾随零都来自哪里?到底是怎么回事?
puts "%.30f" % 9.23
#=> 9.230000000000000426325641456060
由于基地-2(数字计算机内部表示)和基10(你是用什么来处理,并输入到文本编辑器或IRB)之间的差异
,你不能代表9.23 恰好为作为浮点值。这不是特定于Ruby,而是几乎所有的编程语言。
例如,9.23在内部表示为两个大国的总和,是这样的:
01001.00111010111...
||||| ||||||||||+-> 1 * 1/2048 \
||||| |||||||||+--> 1 * 1/1024 \
||||| ||||||||+---> 1 * 1/512 \
||||| |||||||+----> 0 * 1/256 \
||||| ||||||+-----> 1 * 1/128 \
||||| |||||+------> 0 * 1/64 fraction = 0.22998046875
||||| ||||+-------> 1 * 1/32 /
||||| |||+--------> 1 * 1/16 /
||||| ||+---------> 1 * 1/8 /
||||| |+----------> 0 * 1/4 /
||||| +-----------> 0 * 1/2 /
|||||
||||+-------------> 1 * 1 \
|||+--------------> 0 * 2 \
||+---------------> 0 * 4 integer = 9
|+----------------> 1 * 8 /
+-----------------> 0 * 16 /
欲了解更多信息,请阅读What Every Computer Scientist Should Know About Floating Point Arithmetic和IEEE 754 description on Wikipedia。
你的解决方法,当精度是非常重要的(如货币)是:
-
跟踪最小可用单位对你的计算(例如便士),只转换为十进制显示。例如:
result = 2300 + 923 # $23.00 + $9.23 puts "%.2f" % (result/100.0) # Ensure output rounded to two decimal places #=> 32.23
使用图书馆像
BigDecimal
跟踪的准确精度为你,并设置数据库来使用固定精度的数据类型一样DECIMAL or NUMERIC。-
接受数值通常会“足够接近”,并且在向用户显示时总是使用格式化选项。
result = 23 + 9.27 #=> 32.269999999999996 puts "%g" % result #=> 32.27 puts "%.3f" % result #=> 32.270 puts "%.1f" % result #=> 32.3
每当有人使用WECSSKAFPA链接时,都应该颁发帽子。我亲自指出过100次。我总是可以使用moar hatz。 – 2016-10-07 13:08:37
这不是Ruby的问题。这是一个在计算机中表示浮点数的已知问题。
如果您正在进行金融或货币处理,那么您希望远离浮点数来表示您的金额。
这就是你得到处理浮游物。在例如相同的情况下蟒蛇。 – 2012-07-31 21:31:39
在大多数语言中都是一样的。查看http://stackoverflow.com/questions/2100490/floating-point-inaccuracy-examples – 2012-07-31 21:35:00
我认为这是一段时间以来,这个常年最喜欢的想法.. – 2012-07-31 22:28:16