[code]Listbox1.DeleteAllRows
Dim s,r,d As Double
Listbox1.AddRow(“Starting at 1.005”)
For d = 1.005 To 1.155 Step 0.01
r = Round(d * 100) / 100
s = Round((d+0.00001)*100) / 100
listbox1.AddRow(d.ToText,Format(d,“00.00”), Format(r,“00.00”), Format(s,“00.00”))
Next
Listbox1.AddRow(“Starting at 0.905”)
For d = 0.905 To 1.155 Step 0.01
r = Round(d * 100) / 100
s = Round((d+0.00001)*100) / 100
listbox1.AddRow(d.ToText,Format(d,“00.00”), Format(r,“00.00”), Format(s,“00.00”))
Next[/code]
The first listbox entries from the first For…Next are different than the corresponding values on the second For…Next.
I did more tests, it looks like the problem, at least for the Round column is the value for Double. I used a Break statement to see the values directly, even when the double totext = 1.005 the value used is 1.00499999999, that’s why when the for … next statement start with 1.005 it doesn’t round to 1.01
When the for…next start with 0.905 the internal value is also 0.905, that’s why when it reaches 1.005 by adding 0.01 several times the value used is a little above 1.005 and this time the round is done correctly.
If you see the value I assign to s, you will see that I already use your first solution, but with a smaller value:
s = Round((d+0.00001)*100) / 100 is the same as s = Round((d * 100) + 0.001) / 100
The data was just for illustration purposes. I really don’t know what values I’m going to get, so having sometimes 0.005 go up to 0.01 and sometimes down to 0.00 when I use Format “00.00” or other function is something that I have to think how to deal with that.
Do you have this the wrong way round?
Double.totext () is already doing its own rounding.
Doubles are imprecise by definition.
This is why when working with money, many apps use integers and divide at the last minute.
Does this make a difference?
For d = 1005 To 1155 Step 10
r = Round(d * 100) / 100
s = Round((d+0.00001)*100) / 100
listbox1.AddRow(d.ToText,Format(d/1000,"00.00"), Format(r/1000,"00.00"), Format(s/1000,"00.00"))
Next
Sorry Alberto, I didn’t do the whole math for you.
Dave’s example
Is the last hint you need.
1005 rounded is still 1005
1.005 formatted to 00.00 is 1.00
You need 1005 to become 1010 before the division.
So if you want things to round up, add 5
1004 becomes 1009 , divide by 1000 = 1.009 format as 00.00 = 1.00 correct
1005 becomes 1010 divide by 1000 = 1.010 format as 00.00 = 1.01 correct
1999 becomes 2004 divide by 1000 = 2.004 format as 0.00 = 2.00 correct
double is not that precise at all
if you need 2 digits, you can use the currency data type, it will have less rounding errors
you can also use a 64 bits integer, and then divide the result by 100 to get your last number
if you need complete full precision, you can use the decimal plugin : http://delaneyrm.com/DecimalPlugin.html
Doubles are great for science, but not so good for finance or engineering. I would encourage you to use currency data types where accuracy is the goal.
Neither round, nor Currency types work correctly in Xojo
Replacements are available (recent code submitted in https://forum.xojo.com/20531-double-currency/p3#p360693)
Decimal plugin available elsewhere leaks memory
Avoid Currency data type, don’t use round (better to write your own)
And it works. After thinking much about it, Dave and Jeff are correct, is better to just add 0.5, just in case the value internally is 1.0049899 and adding 0.00001 just make the number 1.0049999
Another interesting information, Format(d, “00.00”) do an Arithmetic Rounding, every exact half gets rounded up to the next value, so 1.05 results in 1.10, but Double.ToText(Xojo.Core.Locale.Raw, “00.00”) will give you a Banker’s Rounding also called half-even, where 1.15 goes to nearest even 1.20 and 1.25 also goes to nearest even 1.20.
More interesting is that there is no error using this Double.ToText(Xojo.Core.Locale.Raw, “00.00”), at least for this example. No need to add 0.5 to get the correct results (for Banker’s Rounding).
I am looking on using the Decimal Plugin, I think this is the first time I read it leaks memory. Any information on how bad this is? I’m not working on public apps, just personal/private use.
decimal plugin works great - perfect results, except every time it is instantiated it leaks 416 bytes (multiply that by pay input transactions for hundreds/thousands of staff…I’m sure Bob Delaney would fix it with some encouragement (I haven’t reported it to him bad me, but did test it). This should just be fixed in Xojo and we’d all be happier. Maths on Currency is a dismal failure.
Newbie question, when you say “every time it is instantiated” does it mean like every time I do:
1.- Dim dTest As Decimal
2.- dTest = 15.5 * 18.897
3.- dTest.str
4.- dTest = New Decimal(“3.1415926535897932384626433832795”)
5.- all of the above
I use something like this in a 5 second loop to monitor app leaks (try it with a simple button action that test a currency calc, try it with a WebSegmentedControl which also leaks just by clicking it)
Alberto, try using my Class Money, would be something like:
Dim m As New Money
Listbox1.DeleteAllRows
Dim d As Double
Listbox1.AddRow("Starting at 1.005")
For d = 1.005 To 1.155 Step 0.01
listbox1.AddRow(d.ToText, Format(d,"00.00"), m.Load(d).Round.ToText("00.00"), "?")
Next
....
Wow. I wrote “Money” to avoid the eternal broken Currency, but didn’t know about “Round”, I use it once in this class, do I need to update it with my own “Round” too? Oh Man… I see… Here is the Round thing proof:
MsgBox(“Round(1.015100)="+Round(1.015100).ToText+” and should be 102.0")