I have a simple program for tracking our money, but can't seem to get the decimals under control. I have a variable named money as a double but need to get hose darn decimal points down to 2 n ot the current amount i get. How does one go about making $123.77 instead of 123.772736362627278, and still have accurate math when adding and subtracting from?
I would not use doubles, and instead work internally with integers representing cents, so it will always be exact.
Conversion to Euros with 2 decimal places would then be immediate when you need to show them on screen.
I would not use doubles, and instead work internally with integers representing cents, so it will always be exact.
Conversion to Euros with 2 decimal places would then be immediate when you need to show them on screen.
Correct. I've never worked with bank systems, but I've discussed this with someone who has. And apparently banks always keep the left side of the decimal as one integer, and the right side of the decimal as another integer. It's super important to never, ever have any issues due to imperfect math or unwanted rounding.
So that would be my recommendation also, go for two integer fields if you need it to be accurate.
Correct. I've never worked with bank systems, but I've discussed this with someone who has. And apparently banks always keep the left side of the decimal as one integer, and the right side of the decimal as another integer. It's super important to never, ever have any issues due to imperfect math or unwanted rounding.
So that would be my recommendation also, go for two integer fields if you need it to be accurate.
Using a single integer, if amounts are in the proper range, you could multiply by 100 before storing and divide by 100 when reading back, then use NumberFormat2 to show two decimal places.
B4X:
'$123.77
mymoney = 123.55 * 100 --> 12355 'this will be the value in your DB/permanent storage
'add 22 cents
readytostore = mymoney + 22 --> 12377 'no rounding
'1. store the number on DB as an integer (12377)
'2. read back the number from the DB and show it
backfromstore = 12377 / 100 --> 123.77 'pass this one to NumberFormat to display
Suppose a bank charges 0.1 percent per month during 3 monthes. A client expects (initial contribution) * 1,001 * 1,001 * 1,001.
If to use double, final sum will be the same as in calculator. But if to use integers you will round to 1 cent every month.
Of course, nobody worry about 1 cent. But anyway for which purpose to confuse clients ?
BigDecimal is a good option. Doubles with NumberFormat will also work. Make sure to only convert the real values with NumberFormat when you want to show them. Never convert the string back to a number.
Shoudn't you multiply by 1000 and divide by 1000 in that case? After all you are showing three significant decimal places, no more two as for the OP request.
I anyway agree that this trick is applicable in some circumstances and not in others
I would not use doubles, and instead work internally with integers representing cents, so it will always be exact.
Conversion to Euros with 2 decimal places would then be immediate when you need to show them on screen.
I must agree with Jordi decimals shouldn't be used with money. It would be much more practical to create for ex. Type money that holds the exact value in two different integers.
Because I hate repeating what is in the link? Would this help, even though I'm just verbatim quoting the link?
This object provides arbitrary-precision signed decimal numbers. It is intended for use where absolute
accuracy is required, the classic example being financial computations where the intrinsic
approximations of Floats and Doubles to exact decimal values are unacceptable.
No, because you made zero effort in explaining why it was relevant. That's fine, that's your decision. However, if you show no effort I will not waste a click on it to investigate for you.
Yes, that's an improvement. Even better would be to simply write something like "It's meant for financial computations", which would add a lot of value to the link.
Just reading the actual url I interpreted it to be something scientific that one would use when one need computations with many more decimal places than one usually require. Which isn't really what we were talking about, representing money as two integers.
I have a simple program for tracking our money, but can't seem to get the decimals under control. I have a variable named money as a double but need to get hose darn decimal points down to 2 n ot the current amount i get. How does one go about making $123.77 instead of 123.772736362627278, and still have accurate math when adding and subtracting from?
I would not use doubles, and instead work internally with integers representing cents, so it will always be exact.
Conversion to Euros with 2 decimal places would then be immediate when you need to show them on screen.
I have already distributed an App that manages the personal portfolio and the first cash desk.
I used the Double with a sub that corrected the errors generated by the floating point. The thing is really complex and at the closing of cash every six months, the cash team of 1 cent.
The @JordiCP solution is the least cumbersome one. I have adopted it in subsequent versions.
It's right there in the second sentence of the link. BTW, me posting the link means that I did do the research for you. Why else would I post the link? That did take my time and effort to find. It just happens that the opening paragraph of that link pretty much explains everything. Still perplexed about the whole I did not spend time on the solution thing though.
It is turning into an interesting discussion because it depends very much on the premises that each one has assumed to be true
If (as I assumed), the app must deal with real cash adding and substracting, for instance to keep track of home expenses, definitely taking the base internal unit to be the same as physic currency (cents) will make things simpler from the start. Using doubles with math imprecissions and having to use an external library to deal with those, will work anyway, but is less portable and unnecessary.
I have deployed closed-loop prepaid systems with RFID cards, embedded systems and PC programs taking this approach at design, and terribly simplified things.
Suppose a bank charges 0.1 percent per month during 3 monthes. A client expects (initial contribution) * 1,001 * 1,001 * 1,001.
If to use double, final sum will be the same as in calculator. But if to use integers you will round to 1 cent every month.