7

I have problem with comparison of two variables of "Real" type. One is a result of mathematical operation, stored in a dataset, second one is a value of an edit field in a form, converted by StrToFloat and stored to "Real" variable. The problem is this: 121,97 not equal to 121,97

As you can see, the program is trying to tell me, that 121,97 is not equal to 121,97... I have read this topic, and I am not copletely sure, that it is the same problem. If it was, wouldn't be both the numbers stored in the variables as an exactly same closest representable number, which for 121.97 is 121.96999 99999 99998 86313 16227 83839 70260 62011 71875 ?

Now let's say that they are not stored as the same closest representable number. How do I find how exactly are they stored? When I look in the "CPU" debugging window, I am completely lost. I see the adresses, where those values should be, but nothing even similar to some binary, hexadecimal or whatever representation of the actual number... I admit, that advanced debugging is unknown universe to me...

Edit: those two values really are slightly different.

enter image description here

OK, I don't need to understand everything. Although I am not dealing with money, there will be maximum 3 decimal places, so "currency" is the way out

BTW: The calculation is:

DATA[i].Meta.UnUsedAmount := DATA[i].AMOUNT - ObjQuery.FieldByName('USED').AsFloat;

In this case it is 3695 - 3573.03

Community
  • 1
  • 1
j.kaspar
  • 751
  • 1
  • 11
  • 29
  • See JIRA RSP-13792. You may want to invoke the `comparevalue` function. – Magoo Mar 19 '16 at 15:19
  • 2
    @Magoo That report is bogus. The compiler behaves correctly. – David Heffernan Mar 19 '16 at 15:24
  • 1
    `StrToFloat` should behave as you say. But what about the other value? How is it calculated. I think you should focus on the actual problem, which we cannot see. – David Heffernan Mar 19 '16 at 15:41
  • Visualize the variable as binary in the inspector/watch window, you will see it's different... – whosrdaddy Mar 19 '16 at 15:46
  • Use `currency` for amounts. All your problems will go away. – Johan Mar 19 '16 at 17:06
  • *How do I find how exactly are they stored?* Looking at your code this is irrelevant. You only want to know if one is larger then the other. As others said, use CompareValue or currency datatype. – Jan Doggen Mar 19 '16 at 18:14
  • @Magoo. That report is indeed bogus. The reporter obviously does not fully understand how floating point works. But comparing floating point values for equality is always a little tricky, and should generally be done by functions using an epsilon value for this, like e.g. `SameValue`. – Rudy Velthuis Mar 22 '16 at 21:10
  • FWIW, the Goldberg link you mention is indeed what explains it. Or, alternatively, [my article about floating point](http://rvelthuis.de/articles/articles-floats.html). – Rudy Velthuis Mar 22 '16 at 21:16

1 Answers1

10

For reasons unknown, you cannot view a float value (single/double or real48) as hexadecimal in the watch list.

However, you can still view the hexadecimal representation by viewing it as a memory dump.
Here's how: Add the variable to the watch list.
Right click on the watch -> Edit Watch...
View it as memory dump

enter image description here

Now you can compare the two values in the debugger.

Never use floats for monetary amounts
You do know of course that you should not use floats to count money.
You'll get into all sorts of trouble with rounding and comparisons will not work the way you want them too.
If you want to work with money use the currency type instead. It does not have these problems, supports 4 decimal places and can be compared using the = operator with no rounding issues.

In your database you use the money or currency datatype.

Johan
  • 74,508
  • 24
  • 191
  • 319
  • Yes, but not when you're working with money. Updated the answer. Unless you know exactly what you're doing equality comparisons with floats are a recipe for disaster – Johan Mar 19 '16 at 18:05
  • Thank you! Would it be possible to briefly describe what am I looking at in the memory dump? I am sorry to say, but I have not been successfull at figuring out... I mean - hexadecimal representation of 121.97 is 0x42f3f0a4 ... – j.kaspar Mar 19 '16 at 18:55
  • The representation is correct for a `double`, you are probably talking about a `single` or a -shudder- `real48`. The binary representation of these values is different. – Johan Mar 19 '16 at 19:05
  • ah, ok, that is beyond my imagination... But thank you very much for help – j.kaspar Mar 19 '16 at 19:06
  • Yes, you are looking at a single, the memory dump for that is: `$A4 $F0 $F3 $42 `. Note that due to the fact that x86 is little endian the bytes are reversed. – Johan Mar 19 '16 at 19:08
  • ah, yes, now I understand. Thanks! – j.kaspar Mar 19 '16 at 19:11
  • 1
    @DavidHeffernan, `amount`, yes I mean currency. In my native tongue the words for monetary amounts and other amounts are different. I keep forgetting that English amounts can also be used to denote boring old quantities of other stuff. – Johan Mar 19 '16 at 23:45
  • "Never use floats for amounts"? Why not? Do you mean never use floats for currency? – David Heffernan Mar 19 '16 at 23:48