Failing to approve, if not, in the Smalltalk Unit test bay

I'm at a dead end. Here is my test file.

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

The statement must not fail. When calculating the square of each element correctly. So I took a β€œstep into the test”, it shows that the result of the squareOfAllElements method and # (1.44 9 26.01 49) are the same, but assert evaluates to false. What for? What am I doing wrong here? Any help is appreciated.

+6
source share
3 answers

Here you are dealing with floating point numbers. Floating point numbers are by definition inaccurate, and you should never compare them using # =.

For more details, see Section 1.1 of the project chapter on Pharo floating point numbers by Example: http://stephane.ducasse.free.fr/Web/Draft/Float.pdf

+8
source

However, the equality equality message, # =, is sent to the collection allegedly returned by #squareOfAllElements.

You can rewrite your test statement as:

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

This will check the same as the previous one, but will run one #assert: for each element.

Another option is to implement the #hasEqualElements: option in terms of Float β†’ # equal: instead of # =.

0
source

As the other answers say, Float is inaccurate. Also remember that by default VisualWorks Float has the same precision (about 7 decimal places), if you put your floating-point number with the letter d, for example 5.1d, you get double precision (about 15 decimal places), less inaccurate, but still inaccurate.

Another source of confusion is that two different Float objects can print with the same approximate decimal representation in VisualWorks.

 5.1 squared printString -> '26.01' 

but

 5.1 squared = 26.01 -> false 

Note that the last Squeak or Pharo prints enough decimal places to distinguish between different Float (and reinterpret them without changes)

 5.1 squared ->26.009999999999998 

Alternatively, you can use the so-called FixedPoint (in VisualWorks or ScaledDecimals in other versions) to perform precise operations:

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

Also be careful with this other trap: FixedPoint (ScaledDecimals) only prints as many tens after the fraction point, as was said, but internally it can contain more (infinitely many).

 5.1s1 squared printString -> '26.0s1' 

but

 5.1s1 squared = 26.01s2 -> true 
0
source

Source: https://habr.com/ru/post/898124/