|
Post by Walt Decker on Oct 14, 2022 15:17:07 GMT -5
Implied IF fails with decimal numbers.
Given: ' A = 2 B = 1 Diff = B - A IF Diff THEN PRINT "DIFFERENCE = "; Diff PRINT Diff
C = 1.06 D = 1 Diff = C - D IF Diff THEN PRINT "DIFFERENCE = "; Diff PRINT Diff
end '
Work-around: IF Diff <> 0.0 THEN "Do something"
|
|
|
Post by Brandon Parker on Oct 14, 2022 23:09:01 GMT -5
I am not certain this is a bug. My understanding is that If...Then has always been able to use comparators for things like checking non-integer numbers (Diff <> 0.0), but if there is no comparator within the If...Then construct, LB expects the expression to be boolean (or most likely just integer) in nature (False = 0, True <> 0 ...).
{:0)
Brandon Parker
|
|
|
Post by Walt Decker on Oct 15, 2022 9:42:14 GMT -5
Working with more structured langues the implied IF means that the variable must not be zero (false) for an action to take place. .06 is not false which is a downfall of having unstructured variables.
It also fails with this:
A = 1.06 B = 1.05 Diff = A - B IF Diff > 0.01 THEN "Do Something"
"Do Something" will be activated even though the difference is not greater than 0.01. This I can understand since 0.01 is one of those binary numbers that can not be accurately represented in binary so the solution is to change the comparison to something like 0.012.
|
|
|
IF Error
Oct 15, 2022 10:00:18 GMT -5
via mobile
Post by Rod on Oct 15, 2022 10:00:18 GMT -5
Well we have two types of numbers in Liberty, integers and floats. Often we don’t even need to care which type is in use.
This simplification is part of Liberty and I like it.
The warning sign for comparisons is the decimal point. Anytime you see a number displayed with a decimal Point you know you are dealing with a float and ALL float comparison and summation issues come into play.
I would really dislike having to type every variable I intend to use. This also forces limited use in specific routines whereas now I can reuse the variable anywhere.
|
|
|
Post by Walt Decker on Oct 15, 2022 12:35:27 GMT -5
And how is the programmer going to determine if the result of an operation will be an integer or a real? Translate the result to a string and look for a decimal? That adds an unnecessary operation.
|
|
|
Post by Brandon Parker on Oct 16, 2022 16:38:34 GMT -5
Well Walt, first of all, you are missing a Print statement in your code above.
The thing you are missing here is that LB handles its numeric typing behind the scenes which is why we had the discussion about forcing values to be floating point numbers when assigning them to a Struct member of type Double. You obviously know about the pitfalls of floating point comparison. When working with differing languages, you HAVE to consider how that language handles numbers. In my understanding of LB 4, it will handle all floating point numbers as double precision behind the scenes (I could be wrong on that, but...). So, when you are comparing your "Diff" variable to 0.001, you are not actually comparing "Diff" as a floating point with 3 decimal places; you are comparing it with many more decimal places, and that is where the issue lies. That being said, this issue is something that can be found, in one form or another, in all languages that are capable of floating-point calculations; it's the rounding that always occurs in the standard that catches things out even for the best of people and languages.
In LB, here is your code showing Diff out to 20 decimal places and you can clearly see that the underlying Smalltalk engine must be comparing Diff with at least a few more digits than 15. If you want to compare a floating point number to another, you can limit the number of decimal places using the "Using()" function and create a rounding function for rounding at the last decimal place you need to compare to. CSC201 teaches that if one is going to compare floating point numbers, one should compare the number to +/- a dead band from the setpoint.
A = 1.06 B = 1.05 Diff = A - B
IF Diff > 0.01 THEN Print "Do Something" Print
'Let's look at what the underlying Smalltalk engine might 'actually be comparing to when evaluating Diff Print Using("#.####################", Diff) Print
'Lets limit Diff to the same decimal places 'we want to compare to IF Val(Using("#.##", Diff)) > 0.01 THEN Print "Do Something Better!"
{:0)
Brandon Parker
|
|