我在 irb for Ruby 中收到了非常有趣且看似不稳定的结果。到底是怎么回事?
这是对的!
>> 23+9.22
=> 32.22
这不是!
>> 23+9.23
=> 32.230000000000004
所有尾随零来自哪里?到底是怎么回事?
我在 irb for Ruby 中收到了非常有趣且看似不稳定的结果。到底是怎么回事?
这是对的!
>> 23+9.22
=> 32.22
这不是!
>> 23+9.23
=> 32.230000000000004
所有尾随零来自哪里?到底是怎么回事?
puts "%.30f" % 9.23
#=> 9.230000000000000426325641456060
由于 base-2(数字的计算机内部表示)和 base-10(您习惯处理并在文本编辑器或 IRB 中输入的内容)之间的差异,您不能将 9.23完全表示为浮点值。这不是特定于 Ruby 的,而是存在于几乎所有编程语言中。
例如,9.23 在内部表示为 2 的幂之和,例如:
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 /
有关更多信息,请阅读每个计算机科学家应该了解的关于浮点运算的知识和Wikipedia 上的 IEEE 754 描述。
当精度很重要(例如货币)时,您的解决方法是:
跟踪计算的最小可用单位(例如便士),并仅转换为十进制以进行显示。例如:
result = 2300 + 923 # $23.00 + $9.23
puts "%.2f" % (result/100.0) # Ensure output rounded to two decimal places
#=> 32.23
使用类似的库BigDecimal
来跟踪您的精确精度,并将您的数据库设置为使用固定精度的数据类型,如DECIMAL 或 NUMERIC。
接受数值通常“足够接近”,并在向用户显示它们时始终使用格式选项,例如
result = 23 + 9.27 #=> 32.269999999999996
puts "%g" % result #=> 32.27
puts "%.3f" % result #=> 32.270
puts "%.1f" % result #=> 32.3
这不是 Ruby 的问题。这是计算机中浮点数表示的已知问题。
如果您正在进行财务或货币处理,那么您希望远离浮点数来表示您的金额。