Format display error again

I believe I’ve poked around this issue in the past, but it’s still causing me embarrassment with my clients. Example:

dim m, r, t as currency
m = 174.3
r = .45
t = m * r
MessageBox Format( t, “#.##”) //displays 78.44
MessageBox Format( t + 1000, “#.##”) //displays 1078.43

So in this case adding 1000 to the total causes a one-cent error in the display.

Has anyone found a simple way to deal with this problem?

Try

dim m, r, t as currency
m = 174.3
r = .45
t = m * r
t = round(t*100)/100
MessageBox Format( t, "#.##") //displays 78.44
MessageBox Format( t + 1000, "#.##") //displays 1078.44

Format change your currency type to double and then do the format/rounding
78.435 to double is 78.4350000000000023
1078.435 to double is 1078.4349999999999454
at least that is what Xojo reports. The first number will be 78.44 the second will be 1078.43 using your format.

1 Like

In the first line, t is 78.435
The second time it is 1078.435
Xojo’s format clearly has a bug here.

Despite Xojo saying that it is needlessly time consuming, the only reliable way to handle currenyc of TWO decimal places is to use integer values 100 times the size, and format afterwards, inserting the point manually

2 Likes

You can also use Decimal Plugin from Bob Delaney and use this code:

dim m, r, t as Decimal
m = 174.3
r = .45
t = m * r
'
DecSetScale(2)  //display only 2 digits
MessageBox t.Str //displays 78.44
t = t + 1000
MessageBox  t.Str //displays 1078.44
2 Likes

Thanks for the replies.

The round(t*100)/100 solution definitely works. But it’s incredible that we have to resort to such an expensive cure for what appears to be a long standing bug.

Bob Delaney’s Decimal Plugin looks interesting, too. My app is large though, I will have to look into what it would take to implement it.

Out of curiosity, I expanded your sample a bit. It seems like the root cause of that error is in 174.3 * 0.45 = 78.435. The rounding is correct when this result is formatted to “#.##”.
After adding +1000, the calculation is still right but the 2 decimals-formatted string is not.

Rounding and formatting currency depends on the type of currency. Different rules apply. Take a penny, leave a penny :no_mouth:

For simplicity, why not add a method to a module:
image

Then change the code from


MessageBox Format( t, "#.##") 
MessageBox Format( t + 1000, "#.##") 

to be


MessageBox Format2( t, "#.##") 
MessageBox Format2( t + 1000, "#.##")

or

MessageBox Format2( t) 
MessageBox Format2( t + 1000)

…just needs you to add 2 here and there…

This is exactly why we wrote our own format function from the very beginning. Currency is a good concept, except that the framework functions keep converting it to a double, which causes a lot of problems. It would be great if the framework could differentiate a Currency from everything else, but I’m not sure that’s possible at this point. The framework was built when Double was the greatest common denominator, but Currency and Int64 don’t fit into that now.

Interestingly, the debugger is able to display Currency correctly, so it must be possible.

1 Like

Related: https://tracker.xojo.com/xojoinc/xojo/-/issues/63721

.toString("#.##") works fine

3 Likes

Alas not on a currency type.

See https://tracker.xojo.com/xojoinc/xojo/-/issues/61574

Put your :+1: votes in.

Use UInt64’s, divide by 100 only on display and hope your customers don’t have more than 184467440737095516.15 in their bank accounts :wink:

1 Like

I remember that I asked this some time ago:
#51191
back then the push was to use .ToText

As Julian said, there is no Currency.ToString yet, can’t compile.

I tested using Double instead of currency:
Interesting that format gives 78.44 and 1078.43
but Double.ToString gives 78.44 and 1078.44

Test code:

Dim m, r, t As Currency
m = 174.3
r = .45
t = m * r
//convert t from Currency to Double
Dim v As Double = t
//test format v
MessageBox Format( v, "#.##") //displays 78.44
MessageBox Format( v + 1000, "#.##") //displays 1078.43
//test v.ToString
MessageBox v.ToString("#.##") //displays 78.44
v = v + 1000
MessageBox v.ToString("#.##") //displays 1078.44

I learned, no long ago, that Format and ToString use different code, that’s why we get this difference. For OPs problem, just adding .ToString to Currency will fix the problem.

1 Like