Compare doubles: 50000.3 > 50000.3 = true!?

I encounter some strange behaviour of a greater than comparison:

var teststring as string = "50000.3"
var testdouble as double = teststring.toDouble
var testcalc as double = 50000.1+0.2
var test as Boolean = testdouble > testcalc
System.DebugLog "test = "+test.ToString  // outputs true!?

why might that be?

Do you need to check if one is bigger or is it enough to know if they are equal / unequal?

https://documentation.xojo.com/api/code_execution/equals.html

1 Like

I would like to hear from Xojo, that the calculated 50000.3 is not smaller than the “string-originated” 50000.3
50000.3 > 50000.3 should be false, hence:
testdouble > testcalc should be false
But Xojo gives out a “true”!

check the debugger you’ll see a double is not to be expected as-is.

50000.3 could as well be stored as 50000.2999999999999999999999999999999999 in your computer.
It’s not a xojo thing, it’s how doubles work.

System.DebugLog "testdouble = "+testdouble.toString+", testcalc = "+testcalc.ToString

gives out:
testdouble = 50000.300000, testcalc = 50000.300000

You’re not seeing the actual 15-digit fractional portion. ToString is rounding it. You cannot reliably compare double values. That’s what Equals is for: Equal to a given number of decimals. Or round both values yourself and compare. As @DerkJ said, it’s just the nature of double precision in computer programming. There’s a reason they’re not used for monetary applications.

FWIW,
50000.3 is stored as 50000.300000000003
50000.1 is 50000.099999999999
50000.1 + 0.2 is 50000.299999999999

So, yes, testdouble is greater than testcalc.

50000.300000000003 > 50000.299999999999

1 Like

Crazy. Thank you for the detailed explanation.

No. Try to express 0.1 in binary and you’ll understand …

Not crazy. It’s how floating point works.

1 Like

If the CPU could split the number (the integer and decimal parts) and use both as integers, this problem wouldn’t exist. But probably this would be incompatible with how they could or couldn’t work…

1 Like

Most pocket calculators work that way. But the deduction is incorrect. Try division or taking roots or sinus or numbers like pi etc and you are back to square one - you do Maths with limited precision.

Awesome, I didn’t know about Double.Equals, and I happen to have a need right now, thanks! This forum rocks :slight_smile:

6 Likes

I need greater than or less than on doubles. The numbers really only have on decimal place ie. 14.3

These are both 14.3 but they’re 4.2999999999999998 and 4.3000000000000007 in double so is x < y? should be false but it’s not.

I don’t work with such precision, but 14.3 or 14.35. That’s all I need compare.

So do I have to do something like x = val(x.toString)?

Currency normalize the values to 4 decimal digits, so such small differences vanishes.

Both ends as a fixed currency 4.3000 that if converted back to Double would and as 4.2999999999999998

1 Like

I’ll try this. My second question had been how to convert from double to currency, but you’ve made it really easy.

1 Like

currency or in databases money,decimal,numeric

have a look at CType()
https://documentation.xojo.com/api/language/ctype.html

if you need to compare doubles similar to equal you could use this
if Abs(a-b)< 0.0000001

Turns out currency worked just fine. What doesn’t xojo have a decimal point type?

What a weird fix . . . . .

1 Like

Double.equals has what you need
https://documentation.xojo.com/api/data_types/double.html#double-equals

2 Likes

But when dealing with money, wanting precision to the cents, currency is what you want to avoid accumulating fractional differences up and down. But this conversation leads to more factors, like how you store and recover and mix values without losing precision during possible conversions.

Yes, Xojo having some decimal type with arbitrary precision compatible with current SQL standards, where 12.34 and 12.34000000 are the exact same thing for a Decimal(20,8) would be great.