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) ].

これは前のものと同じようにテストしますが、要素ごとに 1 つの #assert: を実行します。

他のオプションは、#= の代わりに Float>>#equal: に関して #hasEqualElements: のバリエーションを実装することです。

于 2011-10-18T00:55:11.783 に答える
0

他の回答で述べたように、フロートは不正確です。また、Visualworks Float の既定値は単精度 (小数点以下約 7 桁) であることも覚えておいてください。浮動小数点数に文字 d を付けると、5.1d のように倍精度 (小数点以下約 15 桁) になり、不正確さは減りますが、それでも不正確になります。

混乱のもう 1 つの原因は、2 つの異なる Float が Visualworks で同じ近似 10 進数表現で印刷できることです。

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 に答える