6

我难住了。这是我的测试用例。

theTestArray := #(1.2 3 5.1 7).
self assert: theTestArray  squareOfAllElements = #(1.44 9 26.01 49).

断言不应失败。在计算每个元素的平方是正确的。所以我做了“步入测试”,表明方法 squareOfAllElements 和 #(1.44 9 26.01 49) 的结果都是相同的,但 assert 的计算结果为 false。为什么?我在这里做错了什么?任何帮助表示赞赏。

4

3 回答 3

8

你在这里处理浮点数。浮点数的定义是不精确的,你永远不应该使用 #= 来比较它们。

有关详细信息,请查看关于Pharo浮点数的章节草案第 1.1 节,例如:http ://stephane.ducasse.free.fr/Web/Draft/Float.pdf

于 2011-09-27T05:31:27.983 回答
0

但是,比较相等消息#= 被发送到可能由#squareOfAllElements 返回的集合。

您可以将测试语句重写为:

theTestArray := #(1.2 3 5.1 7).
theSquaredArray := theTestArray collect: [:each | each squared].
theTestArray  with: theSquaredArray do: [:a :b | self assert: (a equals: b) ].

这将与前一个测试相同,但将运行一个 #assert: 每个元素。

其他选项是实现#hasEqualElements: 的变体,用Float>>#equal: 代替#=。

于 2011-10-18T00:55:11.783 回答
0

正如在其他答案中所说,浮点数是不精确的。还请记住,Visualworks Float 默认为单精度(约 7 个小数位),如果您使用字母 d 对浮点数进行后缀,例如 5.1d,您将获得双精度(约 15 个小数位),不那么不精确,但仍然不精确。

另一个令人困惑的来源是两个不同的浮点数可以在 Visualworks 中以相同的近似十进制表示形式打印。

5.1 squared printString
-> '26.01'

5.1 squared = 26.01
-> false

请注意,最近的 Squeak 或 Pharo 打印的小数刚好足以区分不同的 Float(并重新解释它们不变)

5.1 squared
->26.009999999999998

或者,您可以使用所谓的 FixedPoint(在 VisualWorks 中或其他风格中的 ScaledDecimals)来执行精确操作:

theTestArray := #(1.2s 3 5.1s 7).
self assert: theTestArray  squareOfAllElements = #(1.44s 9 26.01s 49).

还要注意这个其他陷阱:FixedPoint (ScaledDecimals) 只在小数点之后打印它被告知的小数点,但在内部它可以容纳更多(无限多)。

5.1s1 squared printString
-> '26.0s1'

5.1s1 squared = 26.01s2
-> true
于 2012-07-17T21:50:49.687 回答