【问题标题】:Assertions with storing/retrieving floating point numbers存储/检索浮点数的断言
【发布时间】:2012-08-02 19:37:41
【问题描述】:

(这个问题是在 Ruby 上下文中提出的,但如果以更一般的方式回答,我不会感到不安。)

所以(几乎)每个人都知道,比较数学计算中涉及的浮点数是否相等是行不通的,您必须测试范围(在 Ruby 中,就像这样):

assert_in_delta 5.0, 3.5+1.5, 0.0001

但是,当浮点数从一个子系统传递到另一个子系统时,例如(在 Ruby 上下文中)这样检查浮点数是否相等时,这是否仍然必要?

json={:foo => 0.5}.to_json
# POST the JSON to a Rails controller, that puts it in a Mongo database
found_obj=pull_obj_out_of_Mongo # details not important here
assert_in_delta 0.5, found_obj[:foo], 0.0001

我个人认为 assert_in_delta 在这里仍然是一个好主意,因为我不知道,也许很多人不知道,概念浮点值 0.5 是否以使其能够与带有等号的浮点文字 0.5 进行比较。真的是这样吗,还是我对浮点数的存储和传递方式过于偏执?答案在多大程度上取决于所使用的语言?

【问题讨论】:

  • 顺便提一下,5.0 == (3.5 + 1.5) 返回true。像Math::acos(1.0/Math::sqrt(2)) == Math::PI/4 这样的情况会返回false,因为存在大约1e-16 的差异。涉及非常大和非常小的数字的总和也是有问题的:2.0e19 + 5.0 - 2.0e19 结果是 0.0,而不是 5.0(双精度没有足够的精度位,所以 5.0 被舍入)。

标签: ruby ruby-on-rails-3 unit-testing testing


【解决方案1】:

这在很大程度上取决于子系统对 Float 的作用。在 Ruby(至少 1.8 和 1.9)中,浮点数只是包装一个双精度数字(在 C 中字面意思是 double,在大多数现代架构上存储为 IEEE 754 double-precision number)。当您传递数字或以该表示形式复制数字时,这些位不会改变。

但是,当您将 Float 传递给子系统时,它可能会更改底层表示。在您给出的示例中,您使用 JSON 序列化数字,这涉及将浮点数转换为字符串,然后将其转换回来。无法保证您将恢复超过 15-16 位的准确度(假设您以该准确度进行转换)。这似乎很多,但不足以确保所有可能的浮点值的严格相等。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-29
    • 2013-08-18
    • 1970-01-01
    相关资源
    最近更新 更多