Double - Currency

I could have sworn I submitted one long ago
<https://xojo.com/issue/41735>

Still it would be good if the basic stuff in Xojo would work well.
I wonder what may be going wrong?

Currency could internally be handled like int64 for most operations.
e.g. for adding one to other. What could go wrong that the div fails?

Please Xojo Inc. take the message in this thread highly serious and prioritize these matters above adding new stuff.
We dealt with it far too long.

[code]Sub Action()
// currency maths test
dim a, b, c as currency=0.00

a=15563.12
b=4.3333
c=a/b
a=a/b

break

End Sub[/code]

Still broken 2 years laterā€¦

Thank you Matthew.

I didnā€™t know that currency is not working with 4 decimals, at least in this case it looks like b is only using 4.33

Edit: in Matthewā€™s example a/b=3594.2539 and should be 3591.5168
15563.12 / 4.33 = 3594.2540 (so 4.33 is used instead of 4.3333 above)
but 3591.5168 * 4.3333 = 15563.1197 (this is correct)

Currency is still quite broken in 64 bit builds (issue 47822):

[code]dim c1 as Currency = 1.1
dim c2 as Currency = 1.2

if c1 = c2 then
Break // Should not break here
End[/code]

Thank you David. Your code works in 32 bit but breaks in 64 bit.

As a workaround I changed the If statement to:
If c1.ToText = c2.ToText Then
and it seems to work.

Any other workaround until the issue is fixed?

Edit: I saw your other code (47822). At the break point d4 is reported as 0.799999ā€¦ and d5 as 0.8, so d4 <> d5. But d4.ToText is reported as 0.8000ā€¦ the same as d5.ToText. I guess this is a coincidence and not something that we can use every time, right?

The additional sample code I added to 47822 was an example of why using doubles rather than currency can be a bad idea. People using currency want to avoid issues that arise from using doubles with decimals.

Unfortunately the Currency type is badly broken in 64 builds.

Thank you David.

I agree, Iā€™m writing an app that need the Currency type working and it will be better if it had more decimals. In Mexico there were a lot of changes in currency, 1,000 old pesos now are only 1. I need to do some calculations with 5 decimals.

Iā€™ll try Bob Delaney Decimal plugin. I hope that will help with my project. I didnā€™t want to use any plugin for this, I donā€™t know about licensing but this is a personal project so I think I donā€™t have to worry about that yet.

you can also make your own currency class, with an integer part for the decimals, an int64 for the real part
and rewrite the base operators the way you want, with the decimals you want.

Thank you Jean-Yves, way above my programing knowledge. Maybe in the future.

For now Iā€™ll use the Decimal plugin. I already did some tests and it works perfect for what I need.

I wish Xojo can include a Numeric data type, like PostgreSQL, in the future. It can replace Currency and we can use it to up to 16,383 digits after the decimal point. I donā€™t think I should ever need more than 16.

something like this :

Dim n1,n2 As nativeCurrency

n1.SetNumberOfDecimals( 3)

n1 = "12532.235"
n2 = 52635.952

MsgBox n1 + n2

outputs ā€œ65168.187ā€ as a string or a double as you like

quick and dirty implementation, someone can surely optimize this.

Class nativeCurrency
Methods

Function Operator_Add(rightSide as nativeCurrency) As nativeCurrency 
' adds two nativeCurrency
Dim newCurrency As new nativeCurrency
dim fracLimit as Integer = Pow(10, numberOfDecimals)
newCurrency.fractionnalPart = Me.fractionnalPart + rightSide.fractionnalPart 
newCurrency.integerPart = Me.integerPart + rightSide.integerPart
if newCurrency.fractionnalPart>fracLimit Then
      newCurrency.fractionnalPart = newCurrency.fractionnalPart - fracLimit
newCurrency.integerPart = newCurrency.integerPart + 1 
End If
Return newCurrency 
End Function

Function Operator_Convert() As Double
' converts a nativeCurrency to a Double
Dim fracLimit As Integer = Pow(10, numberOfDecimals)
Dim result As Double
result = Me.integerPart + (Me.fractionnalPart / fracLimit) 
Return result
End Function

Function Operator_Convert() As String
   ' converts a nativeCurrency to a String
Dim result As String
Dim fracLimit As Integer = Pow(10, numberOfDecimals)
Dim fracLimitStr As String = Str( fracLimit) 
fracLimitStr = Right( fracLimitStr, Len(fracLimitStr)-1)
result = Str(Me.integerPart) + "." + Format(Me.fractionnalPart, fracLimitStr)
Return result 
End Function

Sub Operator_Convert(rightSide as String)
' converts a string "xxxx.yyy" to a nativeCurrency
Dim fracLimit As Integer = Pow(10, numberOfDecimals) 
Me.integerPart = Val(NthField(rightSide, ".", 1))
Me.fractionnalPart = Val(NthField(rightSide, ".", 2)) 
End Sub

Sub Operator_Convert(rightSide as Double)
' converts a double xxxx.yyy to a nativeCurrency
Dim fracLimit As Integer = Pow(10, numberOfDecimals)
Me.integerPart = Floor(rightSide)
Dim i As Double = rightSide-Me.integerPart 
dim j as Double = i * fracLimit Me.fractionnalPart = Round(j)
End Sub

Shared Methods

Shared Sub SetNumberOfDecimals(number as Integer) 
numberOfDecimals = number
End Sub

Properties
Private fractionnalPart As Int64
Private integerPart As Int64

Shared Properties
Private Shared numberOfDecimals As Integer

End Class
1 Like