New Framework, ToText and rounding

From another thread I found how to use format with integer.ToText, and after reading about the use of 1-9 for rounding purposes I did some tests and I’m having different results on values I think is not consistent.

Let’s say that you want to round a value to 5 cents, because there are no 1 cent coins in your country (example), so I’m using this:

label4.Text = value2.ToText(xojo.core.locale.raw, "#,##0.05")

That way if I have 0.025 or less, the number shown is 0.00, if the number is 0.0251 it shows 0.05
The problem is with 0.075, it shows 0.10 and I expected 0.05.
Edit: 0.025 should be 0.05, 0.075 is correct at 0.10 (see my note on next post)

Then I changed the format value to #,##0.03, the results I get:
0.015 - 0.00 <-- should be 0.03
0.045 - 0.06
0.075 - 0.06 <-- should be 0.09
0.105 - 0.12
0.135 - 0.12 <-- should be 0.15
and so on.

I said, ok, double is not exact, maybe some decimal at the end of those values. So I used Integer and #,#50. The results I get:
25 - 00 <-- should be 50
75 - 100
125 - 100 <-- should be 150
175 - 200

Now #,#30:
15 - 00 <-- should be 30
45 - 60
75 - 60 <-- should be 90
105 - 120
135 - 120 <-- should be 150

NOTE: the information below is working correctly, I didn’t understand the behavior when I first wrote it

When I did the tests for Integer I left the double format as #,##0.03 and I found something strange too:
15 - 15.00
25 - 24.99 <-- should be 25
30 - 30.00
45 - 45.00
50 - 50.01 <-- should be 50
60 - 60
75 - 75
90 - 90
100 - 99.99 <-- should be 100
*Edit: I think the issue is that 25, 50 and 100 are not divisible by 3, so I guess this is working right, 25 in format #,##0.03 should be 24.99

More interesting is when you format an integer with decimals and both with rounding, like #,#50.05:
25 - 00
26 - 50.05
75 - 50.05
76 - 100.10
126 - 150.15
BTW, double with same format, get the same results

Now double with #,#50.05:
25.025 - 00
25.026 - 50.05
49.0 - 50.05

I know that you should not use #,##0.05 if you using integers, but I think the program should ignore the .05 if the number has no decimals.

I don’t know if #,#50.05 is a valid rounding format. I can’t find this information on the unicode standard. I can’t think of a situation when you need to round like that. I guess I get carried away testing :slight_smile:

Edit: after reading, testing and understanding a little bit more I know how the #,#50.05 format works:
result = round (value / rounding) * rounding
so for 25, round ( 25 / 50.05) * 50.05 = round ( 0.4995 ) * 50.05 = 0 * 50.05 = 0
so for 25.026, round (25.026 / 50.05) * 50.05 = round ( 0.50000199) * 50.05 = 1 * 50.05 = 50.05

Note: I had to go and lear about round. It looks like 0-0.4999 = 0 and 0.5-0.999 = 1, I don’t know why I had the idea that 0-0.5 = 0 and 0.5001- 0.9999 = 1

From what I learned writing the previous post a format of #,#50 should work like this:

result = round(value / format) * format

for 25:
round(25/50) * 50
round(0.5) * 50
1 * 50
result = 50 <-- I’m getting 0

for 50:
round(50/50) * 50
round(1) * 50
1 * 50
result = 50

for 75:
round(75/50) * 50
round(1.5) * 50
2 * 50
result = 100

for 125:
round(125/50) * 50
round(2.5) * 50
3 * 50
result = 150 <-- I’m getting 100

Other tests:

i As Integer = 1225 then +50 Using -> i.ToText(Xojo.Core.Locale.Raw, "#,#50") 1225 use #,#50 = 1,200 <-- Should be 1,250 1275 use #,#50 = 1,300 1325 use #,#50 = 1,300 <-- Should be 1,350 1375 use #,#50 = 1,400 i = 1105 then +10 Using -> i.ToText(Xojo.Core.Locale.Raw, "#,#10") 1105 use #,#10 = 1,100 <-- Should be 1,110 1115 use #,#10 = 1,120 1125 use #,#10 = 1,120 <-- Should be 1,130 1135 use #,#10 = 1,140

The information here say that the number we want to display will be rounded if there is a patter with 1-9, and how it is determined is be dividing the number with the pattern, round the result and multiply by the pattern, so for:

  • 1225 = round(1225/50) * 50 = 1250
  • 1275 = round(1275/50) * 50 = 1300
  • 1105 = round(1105/10) * 10 = 1110
  • 1115 = round(1115/10) * 10 = 1120

Thank you to Jens that mentioned Banker’s Rounding here.

Integer.ToText(Xojo.Core.Locale.Raw, “#,#50”) or
Double.ToText(Xojo.Core.Locale.Raw, “#,##0.05”)

both do Banker’s Rounding as defined in unicode page as “half-even”.

For example:
Integer.ToText(Xojo.Core.Locale.Raw, “#,#50”)
75 will report as 100 // 75/50 = 1.5 so it goes to 2 * 50 = 100
125 will report as 100 // 125/50 = 2.5 so it goes to 2 * 50 = 100
175 will report as 200 // 175/50 = 3.5 so it goes to 4 * 50 = 200
225 will report as 200 // 225/50 = 4.5 so it goes to 4 * 50 = 200