我很难过。这是我的测试用例。
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。为什么?我在这做错了什么?任何帮助表示赞赏。
答案 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