Page 1 of 1

MoneyStringToCents() and CentsToMoneyString()

Posted: Sun Nov 14, 2021 9:27 am
by firace
Here are two short procedures that I have found useful when working with money values, lately.
Why they are needed: As you may know, using floats is a very bad idea (in all languages) when dealing with money.
Careful: Not thoroughly tested. Comments and bug reports welcome :)

EDIT1: code updated with Stargate's bugfix

Code: Select all

Procedure.q MoneyStringToCents(amount.s, howmanydecimals=2)  
  WholePart.s    = StringField(amount, 1, ".")
  DecimalsPart.s = StringField(amount, 2, ".")
  DecimalsPart  = LSet(DecimalsPart, howmanydecimals, "0")
  ProcedureReturn Val(WholePart + DecimalsPart)
EndProcedure   

;Debug ValF("3.00028224")
Debug MoneyStringToCents("3.00028224")
Debug MoneyStringToCents("324")
Debug MoneyStringToCents("1000000000000002")
Debug "---"

Procedure.s CentsToMoneyString(amount.q, howmanydecimals=2)  
  DecimalsPart.s = Right(Str(amount), howmanydecimals)
  If Len(DecimalsPart) < howmanydecimals : DecimalsPart = RSet(DecimalsPart, howmanydecimals, "0") : EndIf 
  WholePart.s = "0" : If Len(Str(amount)) > howmanydecimals : WholePart.s = Left(Str(amount), Len(Str(amount)) - howmanydecimals) : EndIf 
  result.s = WholePart + "." + DecimalsPart
  ProcedureReturn result.s 
EndProcedure 

Debug centsToMoneyString(2245124)
Debug centsToMoneyString(38224)
Debug centsToMoneyString(5)
Debug centsToMoneyString(400)  ;; €4.00

Re: MoneyStringToCents() and CentsToMoneyString()

Posted: Sun Nov 14, 2021 10:36 am
by STARGÅTE
firace wrote: Sun Nov 14, 2021 9:27 am Why they are needed: As you may know, using floats is a very bad idea (in all languages) when dealing with money.
This is correct. However, you are currently also working with floats.
The function Pow() give a float/double as result. Meaning, the line "Val(WholePart) * Pow(10, howmanydecimals) + Val(DecimalsPart)" is a double.

Such calculation can result in wrong results:

Code: Select all

Debug MoneyStringToCents("1000000000000002")
100000000000000192
Here is my suggestion for correction without floats:

Code: Select all

  ProcedureReturn Val(WholePart + DecimalsPart)

Re: MoneyStringToCents() and CentsToMoneyString()

Posted: Sun Nov 14, 2021 10:57 am
by firace
Good catch! Many thanks for your feedback and bugfix. I have updated the code accordingly.

Re: MoneyStringToCents() and CentsToMoneyString()

Posted: Sun Nov 14, 2021 11:40 am
by Bisonte
I do not use a conversion in that sense. I store the number in the smallest unit (in this case cent). So it is also much better to calculate (eg budget books) and to display the value is simply converted into a string and provided with a comma in the right place ;)