在Smalltalk Unit测试用例中,assert失败了

时间:2011-09-27 05:18:53

标签: floating-point assert smalltalk visualworks

我很难过。这是我的测试用例。

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。为什么?我在这做错了什么?任何帮助表示赞赏。

3 个答案:

答案 0 :(得分:8)

您正在处理浮点数。根据定义浮点数是不精确的,你不应该使用#=。

来比较它们

有关详细信息,请参阅本章草案第1.1节,了解 Pharo by Example 的浮点数:http://stephane.ducasse.free.fr/Web/Draft/Float.pdf

答案 1 :(得分: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:而不是#=。

答案 2 :(得分:0)

正如其他答案中所说,Float是不精确的。还要记住,Visualworks Float默认为单精度(大约7个小数位),如果你用浮点数表示字母d,就像5.1d一样,你会得到双精度(约15个小数位),不太精确,但仍然不精确。 / p>

另一个混淆的原因是两个不同的Float可以在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