FAQ
(Note you're ignoring all but the last error in that big block of
fmt.Sscans.)

Disclaimer: I've never written any financial software. However, thinking
about it it seems that just using int64 to represent a base unit (say,
cents or 1/1000 of cents) would be a reasonable way to go unless you
actually need to represent arbitrarily large currency amounts.

Taking inspiration from the time package, I came up with this:

http://play.golang.org/p/v5mP-_KEce

-Caleb

On Sun, Dec 29, 2013 at 3:16 PM, John Whitton wrote:

Hi all,

I'm trying to work with currencies in go. I'm using a simple shopping cart
example where someone is buying some hamburgers and milkshakes, calculating
tax and the total amount.
You can see the code here http://play.golang.org/p/LevYw2DU7R and below
It took me about 40 lines of code to do this and it did not seem
intuitive.
I know there's been some discussion regarding whether to make the amounts
as integers using cents vs big.Rat
If anyone can show me a simpler way to do this, I'd appreciate it.
I'm at the stage where I'm starting to define my types and datastore
elements and would like to have a sound approach for currency before
continuing.

Regards,

John

// Currency Example
//I want to buy 4 Hamburgers (\$5.50 each) and 2 Milkshakes (\$2.86 each)
// Calcualte the Total Price Before Tax = \$27.72 = 4 * \$5.50 + 2 * \$2.86
// Calculate the Tax (7.65%) amount \$2.12 = \$27.72 * 0.765
// Calculate the Total Price \$29.84 = \$27.72 + \$2.12

package main

import (
"fmt"
"math/big"
)

func main() {

//Define all the variables
HamburgerPrice := new(big.Rat)
HamburgerQty := new(big.Rat)
HamburgerTotPrice := new(big.Rat)
MilkshakePrice := new(big.Rat)
MilshakeQty := new(big.Rat)
MilkshakeTotPrice := new(big.Rat)
Tax := new(big.Rat)
TotalPriceBeforeTax := new(big.Rat)
TaxAmount := new(big.Rat)
TotalPrice := new(big.Rat)

//Scan all the Variables
_, err := fmt.Sscan("5.50", HamburgerPrice)
_, err = fmt.Sscan("4", HamburgerQty)
_, err = fmt.Sscan("2.86", MilkshakePrice)
_, err = fmt.Sscan("2", MilshakeQty)
_, err = fmt.Sscan("0.0765", Tax)
if err != nil {
fmt.Println("error scanning value:", err)
}
//Do the Calculation
HamburgerTotPrice.Mul(HamburgerPrice, HamburgerQty)
MilkshakeTotPrice.Mul(MilkshakePrice, MilshakeQty)
TaxAmount.Mul(TotalPriceBeforeTax, Tax)
//Print the result
fmt.Println("Total Price : \$", TotalPrice.FloatString(2))
}

--
You received this message because you are subscribed to the Google Groups
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an
--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.

## Search Discussions

•  at Dec 30, 2013 at 12:06 am ⇧
Thanks Caleb,

That looks a lot more intuitive and a lot cleaner.
I appreciate the help.

Regards,

John
On Sunday, December 29, 2013 3:37:54 PM UTC-8, Caleb Spare wrote:

(Note you're ignoring all but the last error in that big block of
fmt.Sscans.)

Disclaimer: I've never written any financial software. However, thinking
about it it seems that just using int64 to represent a base unit (say,
cents or 1/1000 of cents) would be a reasonable way to go unless you
actually need to represent arbitrarily large currency amounts.

Taking inspiration from the time package, I came up with this:

http://play.golang.org/p/v5mP-_KEce

-Caleb

On Sun, Dec 29, 2013 at 3:16 PM, John Whitton <john.a....@gmail.com<javascript:>
wrote:
Hi all,

I'm trying to work with currencies in go. I'm using a simple shopping
cart example where someone is buying some hamburgers and milkshakes,
calculating tax and the total amount.
You can see the code here http://play.golang.org/p/LevYw2DU7R and below
It took me about 40 lines of code to do this and it did not seem
intuitive.
I know there's been some discussion regarding whether to make the amounts
as integers using cents vs big.Rat
If anyone can show me a simpler way to do this, I'd appreciate it.
I'm at the stage where I'm starting to define my types and datastore
elements and would like to have a sound approach for currency before
continuing.

Regards,

John

// Currency Example
//I want to buy 4 Hamburgers (\$5.50 each) and 2 Milkshakes (\$2.86 each)
// Calcualte the Total Price Before Tax = \$27.72 = 4 * \$5.50 + 2 * \$2.86
// Calculate the Tax (7.65%) amount \$2.12 = \$27.72 * 0.765
// Calculate the Total Price \$29.84 = \$27.72 + \$2.12

package main

import (
"fmt"
"math/big"
)

func main() {

//Define all the variables
HamburgerPrice := new(big.Rat)
HamburgerQty := new(big.Rat)
HamburgerTotPrice := new(big.Rat)
MilkshakePrice := new(big.Rat)
MilshakeQty := new(big.Rat)
MilkshakeTotPrice := new(big.Rat)
Tax := new(big.Rat)
TotalPriceBeforeTax := new(big.Rat)
TaxAmount := new(big.Rat)
TotalPrice := new(big.Rat)

//Scan all the Variables
_, err := fmt.Sscan("5.50", HamburgerPrice)
_, err = fmt.Sscan("4", HamburgerQty)
_, err = fmt.Sscan("2.86", MilkshakePrice)
_, err = fmt.Sscan("2", MilshakeQty)
_, err = fmt.Sscan("0.0765", Tax)
if err != nil {
fmt.Println("error scanning value:", err)
}
//Do the Calculation
HamburgerTotPrice.Mul(HamburgerPrice, HamburgerQty)
MilkshakeTotPrice.Mul(MilkshakePrice, MilshakeQty)
TaxAmount.Mul(TotalPriceBeforeTax, Tax)
//Print the result
fmt.Println("Total Price : \$", TotalPrice.FloatString(2))
}

--
You received this message because you are subscribed to the Google Groups
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an
--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
•  at Dec 30, 2013 at 7:52 am ⇧
Using floats in financial software is a big nono (rounding issues).

subject in this newsgroup.

Best,
Gerard
On Monday, December 30, 2013 12:16:26 AM UTC+1, John Whitton wrote:

Hi all,

I'm trying to work with currencies in go. I'm using a simple shopping cart
example where someone is buying some hamburgers and milkshakes, calculating
tax and the total amount.
You can see the code here http://play.golang.org/p/LevYw2DU7R and below
It took me about 40 lines of code to do this and it did not seem
intuitive.
I know there's been some discussion regarding whether to make the amounts
as integers using cents vs big.Rat
If anyone can show me a simpler way to do this, I'd appreciate it.
I'm at the stage where I'm starting to define my types and datastore
elements and would like to have a sound approach for currency before
continuing.

Regards,

John

// Currency Example
//I want to buy 4 Hamburgers (\$5.50 each) and 2 Milkshakes (\$2.86 each)
// Calcualte the Total Price Before Tax = \$27.72 = 4 * \$5.50 + 2 * \$2.86
// Calculate the Tax (7.65%) amount \$2.12 = \$27.72 * 0.765
// Calculate the Total Price \$29.84 = \$27.72 + \$2.12

package main

import (
"fmt"
"math/big"
)

func main() {

//Define all the variables
HamburgerPrice := new(big.Rat)
HamburgerQty := new(big.Rat)
HamburgerTotPrice := new(big.Rat)
MilkshakePrice := new(big.Rat)
MilshakeQty := new(big.Rat)
MilkshakeTotPrice := new(big.Rat)
Tax := new(big.Rat)
TotalPriceBeforeTax := new(big.Rat)
TaxAmount := new(big.Rat)
TotalPrice := new(big.Rat)

//Scan all the Variables
_, err := fmt.Sscan("5.50", HamburgerPrice)
_, err = fmt.Sscan("4", HamburgerQty)
_, err = fmt.Sscan("2.86", MilkshakePrice)
_, err = fmt.Sscan("2", MilshakeQty)
_, err = fmt.Sscan("0.0765", Tax)
if err != nil {
fmt.Println("error scanning value:", err)
}
//Do the Calculation
HamburgerTotPrice.Mul(HamburgerPrice, HamburgerQty)
MilkshakeTotPrice.Mul(MilkshakePrice, MilshakeQty)
TaxAmount.Mul(TotalPriceBeforeTax, Tax)
//Print the result
fmt.Println("Total Price : \$", TotalPrice.FloatString(2))
}
--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
•  at Dec 30, 2013 at 3:04 pm ⇧
It would be nice to have full (native) support for decimals in GO with
overloaded operators. With current implementation not only it is hard to
read but you still have to take care of rounding issues
val1:= new (big.Rat)
val1 = val1.SetFloat64(1.1)
val2 := new (big.Rat)
val2.SetFloat64(0.1)
two := big.NewRat(2,1)
fmt.Println(avg.Float64())
On Monday, December 30, 2013 1:52:49 AM UTC-6, Gerard wrote:

Using floats in financial software is a big nono (rounding issues).

subject in this newsgroup.

Best,
Gerard
On Monday, December 30, 2013 12:16:26 AM UTC+1, John Whitton wrote:

Hi all,

I'm trying to work with currencies in go. I'm using a simple shopping
cart example where someone is buying some hamburgers and milkshakes,
calculating tax and the total amount.
You can see the code here http://play.golang.org/p/LevYw2DU7R and below
It took me about 40 lines of code to do this and it did not seem
intuitive.
I know there's been some discussion regarding whether to make the amounts
as integers using cents vs big.Rat
If anyone can show me a simpler way to do this, I'd appreciate it.
I'm at the stage where I'm starting to define my types and datastore
elements and would like to have a sound approach for currency before
continuing.

Regards,

John

// Currency Example
//I want to buy 4 Hamburgers (\$5.50 each) and 2 Milkshakes (\$2.86 each)
// Calcualte the Total Price Before Tax = \$27.72 = 4 * \$5.50 + 2 * \$2.86
// Calculate the Tax (7.65%) amount \$2.12 = \$27.72 * 0.765
// Calculate the Total Price \$29.84 = \$27.72 + \$2.12

package main

import (
"fmt"
"math/big"
)

func main() {

//Define all the variables
HamburgerPrice := new(big.Rat)
HamburgerQty := new(big.Rat)
HamburgerTotPrice := new(big.Rat)
MilkshakePrice := new(big.Rat)
MilshakeQty := new(big.Rat)
MilkshakeTotPrice := new(big.Rat)
Tax := new(big.Rat)
TotalPriceBeforeTax := new(big.Rat)
TaxAmount := new(big.Rat)
TotalPrice := new(big.Rat)

//Scan all the Variables
_, err := fmt.Sscan("5.50", HamburgerPrice)
_, err = fmt.Sscan("4", HamburgerQty)
_, err = fmt.Sscan("2.86", MilkshakePrice)
_, err = fmt.Sscan("2", MilshakeQty)
_, err = fmt.Sscan("0.0765", Tax)
if err != nil {
fmt.Println("error scanning value:", err)
}
//Do the Calculation
HamburgerTotPrice.Mul(HamburgerPrice, HamburgerQty)
MilkshakeTotPrice.Mul(MilkshakePrice, MilshakeQty)
TaxAmount.Mul(TotalPriceBeforeTax, Tax)
//Print the result
fmt.Println("Total Price : \$", TotalPrice.FloatString(2))
}
--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
•  at Dec 30, 2013 at 3:12 pm ⇧

On Mon, Dec 30, 2013 at 4:04 PM, wrote:
It would be nice to have full (native) support for decimals in GO with
overloaded operators. With current implementation not only it is hard to
read but you still have to take care of rounding issues
val1:= new (big.Rat)
val1 = val1.SetFloat64(1.1)
val2 := new (big.Rat)
val2.SetFloat64(0.1)
two := big.NewRat(2,1)
fmt.Println(avg.Float64())
The four basic arithmetic operations are performed exactly for
big.{Int,Rat} typed values. There's nothing to gain here wrt a decimal
type.

Rounding issues are introduced only by using inexact (floating point)
numbers (for no good reason). And, the very same would happen using a
decimal type.

-j

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
•  at Dec 30, 2013 at 3:20 pm ⇧
Yes there is. This is how this formula looks in c#
var avg = (0.1d + 1.1d)/2
printing avg would return 0.6 (something that I expect with decimals)
On Monday, December 30, 2013 9:11:40 AM UTC-6, Jan Mercl wrote:

On Mon, Dec 30, 2013 at 4:04 PM, <shka...@gmail.com <javascript:>>
wrote:
It would be nice to have full (native) support for decimals in GO with
overloaded operators. With current implementation not only it is hard to
read but you still have to take care of rounding issues
val1:= new (big.Rat)
val1 = val1.SetFloat64(1.1)
val2 := new (big.Rat)
val2.SetFloat64(0.1)
two := big.NewRat(2,1)
fmt.Println(avg.Float64())
The four basic arithmetic operations are performed exactly for
big.{Int,Rat} typed values. There's nothing to gain here wrt a decimal
type.

Rounding issues are introduced only by using inexact (floating point)
numbers (for no good reason). And, the very same would happen using a
decimal type.

-j
--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
•  at Dec 30, 2013 at 4:52 pm ⇧
...same works with int64 using values*1000:

var avg = (100 + 1100)/2

John von Neumann did it this way. So can you.

On Mon, Dec 30, 2013 at 7:20 AM, wrote:

Yes there is. This is how this formula looks in c#
var avg = (0.1d + 1.1d)/2
printing avg would return 0.6 (something that I expect with decimals)
On Monday, December 30, 2013 9:11:40 AM UTC-6, Jan Mercl wrote:
On Mon, Dec 30, 2013 at 4:04 PM, wrote:
It would be nice to have full (native) support for decimals in GO with
overloaded operators. With current implementation not only it is hard to
read but you still have to take care of rounding issues
val1:= new (big.Rat)
val1 = val1.SetFloat64(1.1)
val2 := new (big.Rat)
val2.SetFloat64(0.1)
two := big.NewRat(2,1)
fmt.Println(avg.Float64())
The four basic arithmetic operations are performed exactly for
big.{Int,Rat} typed values. There's nothing to gain here wrt a decimal
type.

Rounding issues are introduced only by using inexact (floating point)
numbers (for no good reason). And, the very same would happen using a
decimal type.

-j
--
You received this message because you are subscribed to the Google Groups
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an

--
650-335-5765
*(Note: this email has been shared with you under the terms of Regulation
23 <http://go/cory-eula>)*

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
•  at Dec 30, 2013 at 5:38 pm ⇧
I can, but it doesn't make developer's work easier, nor it makes
calculations more precise. They way I see it right now is: GO does support decimal
(Rat) if you really need it, but it is rather painful to use it for any
(serious) financial/accounting software. I agree for some scenarios
suggested method or even floats would be enough.
On Monday, December 30, 2013 10:51:54 AM UTC-6, Michael Jones wrote:

...same works with int64 using values*1000:

var avg = (100 + 1100)/2

John von Neumann did it this way. So can you.

On Mon, Dec 30, 2013 at 7:20 AM, <shka...@gmail.com <javascript:>> wrote:

Yes there is. This is how this formula looks in c#
var avg = (0.1d + 1.1d)/2
printing avg would return 0.6 (something that I expect with decimals)
On Monday, December 30, 2013 9:11:40 AM UTC-6, Jan Mercl wrote:
On Mon, Dec 30, 2013 at 4:04 PM, wrote:
It would be nice to have full (native) support for decimals in GO with
overloaded operators. With current implementation not only it is hard to
read but you still have to take care of rounding issues
val1:= new (big.Rat)
val1 = val1.SetFloat64(1.1)
val2 := new (big.Rat)
val2.SetFloat64(0.1)
two := big.NewRat(2,1)
fmt.Println(avg.Float64())
The four basic arithmetic operations are performed exactly for
big.{Int,Rat} typed values. There's nothing to gain here wrt a decimal
type.

Rounding issues are introduced only by using inexact (floating point)
numbers (for no good reason). And, the very same would happen using a
decimal type.

-j
--
You received this message because you are subscribed to the Google Groups
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an

--
+1 650-335-5765
*(Note: this email has been shared with you under the terms of Regulation
23 <http://go/cory-eula>)*
--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
•  at Dec 30, 2013 at 7:18 pm ⇧
As I said before, you can also look at other decimal packages. If you
search you will find them. Or create your own. It's not that hard.
On Monday, December 30, 2013 6:38:01 PM UTC+1, shka...@gmail.com wrote:

I can, but it doesn't make developer's work easier, nor it makes
calculations more precise. They way I see it right now is: GO does support decimal
(Rat) if you really need it, but it is rather painful to use it for any
(serious) financial/accounting software. I agree for some scenarios
suggested method or even floats would be enough.
On Monday, December 30, 2013 10:51:54 AM UTC-6, Michael Jones wrote:

...same works with int64 using values*1000:

var avg = (100 + 1100)/2

John von Neumann did it this way. So can you.

On Mon, Dec 30, 2013 at 7:20 AM, wrote:

Yes there is. This is how this formula looks in c#
var avg = (0.1d + 1.1d)/2
printing avg would return 0.6 (something that I expect with decimals)
On Monday, December 30, 2013 9:11:40 AM UTC-6, Jan Mercl wrote:
On Mon, Dec 30, 2013 at 4:04 PM, wrote:
It would be nice to have full (native) support for decimals in GO with
overloaded operators. With current implementation not only it is hard to
read but you still have to take care of rounding issues
val1:= new (big.Rat)
val1 = val1.SetFloat64(1.1)
val2 := new (big.Rat)
val2.SetFloat64(0.1)
two := big.NewRat(2,1)
fmt.Println(avg.Float64())
The four basic arithmetic operations are performed exactly for
big.{Int,Rat} typed values. There's nothing to gain here wrt a decimal
type.

Rounding issues are introduced only by using inexact (floating point)
numbers (for no good reason). And, the very same would happen using a
decimal type.

-j
--
Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send

--
650-335-5765
*(Note: this email has been shared with you under the terms of Regulation
23 <http://go/cory-eula>)*
--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
•  at Dec 30, 2013 at 7:58 pm ⇧
from memory, when working with actual money, what is done is to use
integers, of (for USD) 1/1000 of a cent.

so 1 dollar is represented by 100,000.

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
•  at Dec 30, 2013 at 8:16 pm ⇧
I would probably use something really simple as in
http://play.golang.org/p/DJGVtMFYJf

You can probably add a parsing method too if you need it.

On Mon, Dec 30, 2013 at 11:58 AM, simon place wrote:

from memory, when working with actual money, what is done is to use
integers, of (for USD) 1/1000 of a cent.

so 1 dollar is represented by 100,000.

--
You received this message because you are subscribed to the Google Groups
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an

--
--
Francesc Campoy
http://campoy.cat

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
•  at Dec 31, 2013 at 1:26 am ⇧
Financial institutions don't like fractional pennies:
http://youtu.be/orGNl-S2IoE?t=37s
So, it'll be easier if you used an int64 to represent whole pennies.

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
•  at Dec 31, 2013 at 1:49 am ⇧
C#'s decimal type is 128 bit and follows this spec:

http://en.wikipedia.org/wiki/Decimal128_floating-point_format

It's significantly more complicated than just using an int64 to represent
fractions of a penny.
On Mon, Dec 30, 2013 at 6:25 PM, Sugu Sougoumarane wrote:

Financial institutions don't like fractional pennies:
http://youtu.be/orGNl-S2IoE?t=37s
So, it'll be easier if you used an int64 to represent whole pennies.

--
You received this message because you are subscribed to the Google Groups
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an
--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
•  at Dec 31, 2013 at 2:16 am ⇧
The company I work for interfaces to dozens of payment transaction
processing companies. There is no real standard for the format payment
processors require - int, BCD, ASCII with spaces on the left or right,
fixed and variable widths, etc. I am not aware of any that use float (for
hopefully obvious reasons).

Internally, we use 64-bit integers representing cents and convert to the
appropriate format for the payment processor. We have not had a need yet to
provide fractions of cents, and indeed, most processors don't even support
them yet. Hever it is just as easy to represent fractional cents. Even
going to 1/1,000,000th cent accuracy there would still be plenty of room
for the dollar amount.

The complexity of a general decimal type seems overkill to me. I think
Caleb's example of using ideas similar to the Time Duration type is a good
way to handle currency in Go.

On Sunday, December 29, 2013 4:16:26 PM UTC-7, John Whitton wrote:

Hi all,

I'm trying to work with currencies in go. I'm using a simple shopping cart
example where someone is buying some hamburgers and milkshakes, calculating
tax and the total amount.
You can see the code here http://play.golang.org/p/LevYw2DU7R and below
It took me about 40 lines of code to do this and it did not seem
intuitive.
I know there's been some discussion regarding whether to make the amounts
as integers using cents vs big.Rat
If anyone can show me a simpler way to do this, I'd appreciate it.
I'm at the stage where I'm starting to define my types and datastore
elements and would like to have a sound approach for currency before
continuing.

Regards,

John

// Currency Example
//I want to buy 4 Hamburgers (\$5.50 each) and 2 Milkshakes (\$2.86 each)
// Calcualte the Total Price Before Tax = \$27.72 = 4 * \$5.50 + 2 * \$2.86
// Calculate the Tax (7.65%) amount \$2.12 = \$27.72 * 0.765
// Calculate the Total Price \$29.84 = \$27.72 + \$2.12

package main

import (
"fmt"
"math/big"
)

func main() {

//Define all the variables
HamburgerPrice := new(big.Rat)
HamburgerQty := new(big.Rat)
HamburgerTotPrice := new(big.Rat)
MilkshakePrice := new(big.Rat)
MilshakeQty := new(big.Rat)
MilkshakeTotPrice := new(big.Rat)
Tax := new(big.Rat)
TotalPriceBeforeTax := new(big.Rat)
TaxAmount := new(big.Rat)
TotalPrice := new(big.Rat)

//Scan all the Variables
_, err := fmt.Sscan("5.50", HamburgerPrice)
_, err = fmt.Sscan("4", HamburgerQty)
_, err = fmt.Sscan("2.86", MilkshakePrice)
_, err = fmt.Sscan("2", MilshakeQty)
_, err = fmt.Sscan("0.0765", Tax)
if err != nil {
fmt.Println("error scanning value:", err)
}
//Do the Calculation
HamburgerTotPrice.Mul(HamburgerPrice, HamburgerQty)
MilkshakeTotPrice.Mul(MilkshakePrice, MilshakeQty)
TaxAmount.Mul(TotalPriceBeforeTax, Tax)
//Print the result
fmt.Println("Total Price : \$", TotalPrice.FloatString(2))
}
--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
•  at Dec 31, 2013 at 6:33 pm ⇧
Consider this simple example:
This formula (if you use int64) \$100/\$339*\$10000 in our case would result
in 0 regardless of precision, but should be 2949.8525
With decimals (or Rat) you will get correct result with ints you don't
(unless you complicate the formula to work with reminders too)
For this reason major db vendors implement decimal/numeric support
On Monday, December 30, 2013 8:16:06 PM UTC-6, John Waycott wrote:

The company I work for interfaces to dozens of payment transaction
processing companies. There is no real standard for the format payment
processors require - int, BCD, ASCII with spaces on the left or right,
fixed and variable widths, etc. I am not aware of any that use float (for
hopefully obvious reasons).

Internally, we use 64-bit integers representing cents and convert to the
appropriate format for the payment processor. We have not had a need yet to
provide fractions of cents, and indeed, most processors don't even support
them yet. Hever it is just as easy to represent fractional cents. Even
going to 1/1,000,000th cent accuracy there would still be plenty of room
for the dollar amount.

The complexity of a general decimal type seems overkill to me. I think
Caleb's example of using ideas similar to the Time Duration type is a good
way to handle currency in Go.

On Sunday, December 29, 2013 4:16:26 PM UTC-7, John Whitton wrote:

Hi all,

I'm trying to work with currencies in go. I'm using a simple shopping
cart example where someone is buying some hamburgers and milkshakes,
calculating tax and the total amount.
You can see the code here http://play.golang.org/p/LevYw2DU7R and below
It took me about 40 lines of code to do this and it did not seem
intuitive.
I know there's been some discussion regarding whether to make the amounts
as integers using cents vs big.Rat
If anyone can show me a simpler way to do this, I'd appreciate it.
I'm at the stage where I'm starting to define my types and datastore
elements and would like to have a sound approach for currency before
continuing.

Regards,

John

// Currency Example
//I want to buy 4 Hamburgers (\$5.50 each) and 2 Milkshakes (\$2.86 each)
// Calcualte the Total Price Before Tax = \$27.72 = 4 * \$5.50 + 2 * \$2.86
// Calculate the Tax (7.65%) amount \$2.12 = \$27.72 * 0.765
// Calculate the Total Price \$29.84 = \$27.72 + \$2.12

package main

import (
"fmt"
"math/big"
)

func main() {

//Define all the variables
HamburgerPrice := new(big.Rat)
HamburgerQty := new(big.Rat)
HamburgerTotPrice := new(big.Rat)
MilkshakePrice := new(big.Rat)
MilshakeQty := new(big.Rat)
MilkshakeTotPrice := new(big.Rat)
Tax := new(big.Rat)
TotalPriceBeforeTax := new(big.Rat)
TaxAmount := new(big.Rat)
TotalPrice := new(big.Rat)

//Scan all the Variables
_, err := fmt.Sscan("5.50", HamburgerPrice)
_, err = fmt.Sscan("4", HamburgerQty)
_, err = fmt.Sscan("2.86", MilkshakePrice)
_, err = fmt.Sscan("2", MilshakeQty)
_, err = fmt.Sscan("0.0765", Tax)
if err != nil {
fmt.Println("error scanning value:", err)
}
//Do the Calculation
HamburgerTotPrice.Mul(HamburgerPrice, HamburgerQty)
MilkshakeTotPrice.Mul(MilkshakePrice, MilshakeQty)
TaxAmount.Mul(TotalPriceBeforeTax, Tax)
//Print the result
fmt.Println("Total Price : \$", TotalPrice.FloatString(2))
}
--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
•  at Dec 31, 2013 at 7:12 pm ⇧
One always multiplies before dividing in scaled integer arithmetic.
http://en.wikipedia.org/wiki/Fixed-point_arithmetic

In Forth, there is a special "MulDiv" operator "a b c */" that computes a*b
in doubled integer precision and then divides the high precision result by
c. It turns out that almost everything can be solved using MulDiv.

On Tue, Dec 31, 2013 at 10:33 AM, wrote:

Consider this simple example:
This formula (if you use int64) \$100/\$339*\$10000 in our case would result
in 0 regardless of precision, but should be 2949.8525
With decimals (or Rat) you will get correct result with ints you don't
(unless you complicate the formula to work with reminders too)
For this reason major db vendors implement decimal/numeric support
On Monday, December 30, 2013 8:16:06 PM UTC-6, John Waycott wrote:

The company I work for interfaces to dozens of payment transaction
processing companies. There is no real standard for the format payment
processors require - int, BCD, ASCII with spaces on the left or right,
fixed and variable widths, etc. I am not aware of any that use float (for
hopefully obvious reasons).

Internally, we use 64-bit integers representing cents and convert to the
appropriate format for the payment processor. We have not had a need yet to
provide fractions of cents, and indeed, most processors don't even support
them yet. Hever it is just as easy to represent fractional cents. Even
going to 1/1,000,000th cent accuracy there would still be plenty of room
for the dollar amount.

The complexity of a general decimal type seems overkill to me. I think
Caleb's example of using ideas similar to the Time Duration type is a good
way to handle currency in Go.

On Sunday, December 29, 2013 4:16:26 PM UTC-7, John Whitton wrote:

Hi all,

I'm trying to work with currencies in go. I'm using a simple shopping
cart example where someone is buying some hamburgers and milkshakes,
calculating tax and the total amount.
You can see the code here http://play.golang.org/p/LevYw2DU7R and below
It took me about 40 lines of code to do this and it did not seem
intuitive.
I know there's been some discussion regarding whether to make the
amounts as integers using cents vs big.Rat
If anyone can show me a simpler way to do this, I'd appreciate it.
I'm at the stage where I'm starting to define my types and datastore
elements and would like to have a sound approach for currency before
continuing.

Regards,

John

// Currency Example
//I want to buy 4 Hamburgers (\$5.50 each) and 2 Milkshakes (\$2.86 each)
// Calcualte the Total Price Before Tax = \$27.72 = 4 * \$5.50 + 2 * \$2.86
// Calculate the Tax (7.65%) amount \$2.12 = \$27.72 * 0.765
// Calculate the Total Price \$29.84 = \$27.72 + \$2.12

package main

import (
"fmt"
"math/big"
)

func main() {

//Define all the variables
HamburgerPrice := new(big.Rat)
HamburgerQty := new(big.Rat)
HamburgerTotPrice := new(big.Rat)
MilkshakePrice := new(big.Rat)
MilshakeQty := new(big.Rat)
MilkshakeTotPrice := new(big.Rat)
Tax := new(big.Rat)
TotalPriceBeforeTax := new(big.Rat)
TaxAmount := new(big.Rat)
TotalPrice := new(big.Rat)

//Scan all the Variables
_, err := fmt.Sscan("5.50", HamburgerPrice)
_, err = fmt.Sscan("4", HamburgerQty)
_, err = fmt.Sscan("2.86", MilkshakePrice)
_, err = fmt.Sscan("2", MilshakeQty)
_, err = fmt.Sscan("0.0765", Tax)
if err != nil {
fmt.Println("error scanning value:", err)
}
//Do the Calculation
HamburgerTotPrice.Mul(HamburgerPrice, HamburgerQty)
MilkshakeTotPrice.Mul(MilkshakePrice, MilshakeQty)
TaxAmount.Mul(TotalPriceBeforeTax, Tax)
//Print the result
fmt.Println("Total Price : \$", TotalPrice.FloatString(2))
}

--
You received this message because you are subscribed to the Google Groups
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an

--
650-335-5765
*(Note: this email has been shared with you under the terms of Regulation
23 <http://go/cory-eula>)*

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
•  at Dec 31, 2013 at 7:32 pm ⇧
I doubt anyone writing financial software would consider first option. It
is error prone. It changes formulas e.g. (100/339 + 1)*10000 would result
in 100*10000/339 + 1*10000. So far big.Rat is the winner but it is not easy
to work with that either. I'm not familiar with MulDiv operator
On Tuesday, December 31, 2013 1:11:44 PM UTC-6, Michael Jones wrote:

One always multiplies before dividing in scaled integer arithmetic.
http://en.wikipedia.org/wiki/Fixed-point_arithmetic

In Forth, there is a special "MulDiv" operator "a b c */" that computes
a*b in doubled integer precision and then divides the high precision result
by c. It turns out that almost everything can be solved using MulDiv.

On Tue, Dec 31, 2013 at 10:33 AM, <shka...@gmail.com <javascript:>> wrote:

Consider this simple example:
This formula (if you use int64) \$100/\$339*\$10000 in our case would result
in 0 regardless of precision, but should be 2949.8525
With decimals (or Rat) you will get correct result with ints you don't
(unless you complicate the formula to work with reminders too)
For this reason major db vendors implement decimal/numeric support
On Monday, December 30, 2013 8:16:06 PM UTC-6, John Waycott wrote:

The company I work for interfaces to dozens of payment transaction
processing companies. There is no real standard for the format payment
processors require - int, BCD, ASCII with spaces on the left or right,
fixed and variable widths, etc. I am not aware of any that use float (for
hopefully obvious reasons).

Internally, we use 64-bit integers representing cents and convert to the
appropriate format for the payment processor. We have not had a need yet to
provide fractions of cents, and indeed, most processors don't even support
them yet. Hever it is just as easy to represent fractional cents. Even
going to 1/1,000,000th cent accuracy there would still be plenty of room
for the dollar amount.

The complexity of a general decimal type seems overkill to me. I think
Caleb's example of using ideas similar to the Time Duration type is a good
way to handle currency in Go.

On Sunday, December 29, 2013 4:16:26 PM UTC-7, John Whitton wrote:

Hi all,

I'm trying to work with currencies in go. I'm using a simple shopping
cart example where someone is buying some hamburgers and milkshakes,
calculating tax and the total amount.
You can see the code here http://play.golang.org/p/LevYw2DU7R and below
It took me about 40 lines of code to do this and it did not seem
intuitive.
I know there's been some discussion regarding whether to make the
amounts as integers using cents vs big.Rat
If anyone can show me a simpler way to do this, I'd appreciate it.
I'm at the stage where I'm starting to define my types and datastore
elements and would like to have a sound approach for currency before
continuing.

Regards,

John

// Currency Example
//I want to buy 4 Hamburgers (\$5.50 each) and 2 Milkshakes (\$2.86 each)
// Calcualte the Total Price Before Tax = \$27.72 = 4 * \$5.50 + 2 * \$2.86
// Calculate the Tax (7.65%) amount \$2.12 = \$27.72 * 0.765
// Calculate the Total Price \$29.84 = \$27.72 + \$2.12

package main

import (
"fmt"
"math/big"
)

func main() {

//Define all the variables
HamburgerPrice := new(big.Rat)
HamburgerQty := new(big.Rat)
HamburgerTotPrice := new(big.Rat)
MilkshakePrice := new(big.Rat)
MilshakeQty := new(big.Rat)
MilkshakeTotPrice := new(big.Rat)
Tax := new(big.Rat)
TotalPriceBeforeTax := new(big.Rat)
TaxAmount := new(big.Rat)
TotalPrice := new(big.Rat)

//Scan all the Variables
_, err := fmt.Sscan("5.50", HamburgerPrice)
_, err = fmt.Sscan("4", HamburgerQty)
_, err = fmt.Sscan("2.86", MilkshakePrice)
_, err = fmt.Sscan("2", MilshakeQty)
_, err = fmt.Sscan("0.0765", Tax)
if err != nil {
fmt.Println("error scanning value:", err)
}
//Do the Calculation
HamburgerTotPrice.Mul(HamburgerPrice, HamburgerQty)
MilkshakeTotPrice.Mul(MilkshakePrice, MilshakeQty)
TaxAmount.Mul(TotalPriceBeforeTax, Tax)
//Print the result
fmt.Println("Total Price : \$", TotalPrice.FloatString(2))
}

--
You received this message because you are subscribed to the Google Groups
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an

--
+1 650-335-5765
*(Note: this email has been shared with you under the terms of Regulation
23 <http://go/cory-eula>)*
--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
•  at Jan 1, 2014 at 4:29 pm ⇧

On Tuesday, December 31, 2013 12:32:01 PM UTC-7, shka...@gmail.com wrote:
I doubt anyone writing financial software would consider first option. It
is error prone. It changes formulas e.g. (100/339 + 1)*10000 would result
in 100*10000/339 + 1*10000. So far big.Rat is the winner but it is not easy
to work with that either. I'm not familiar with MulDiv operator
On Tuesday, December 31, 2013 1:11:44 PM UTC-6, Michael Jones wrote:

One always multiplies before dividing in scaled integer arithmetic.
http://en.wikipedia.org/wiki/Fixed-point_arithmetic

In Forth, there is a special "MulDiv" operator "a b c */" that computes
a*b in doubled integer precision and then divides the high precision result
by c. It turns out that almost everything can be solved using MulDiv.
All of the programmers I've known who have written financial software
dealing with division and multiplication are well aware of the pitfalls of
dividing before multiplying. It is a well-studied problem.

I think you mean \$100/339*10000. I can't imagine any case where you would
multiply two currency values. The results are nonsensical. \$10/\$5 is an
untyped number which might be useful, but the result is not currency. Is
\$20 * \$30 = 600 square-dollars? Seriously, using a decimal package might
make sense for complex calculations such as compounding interest, but I'd
wager most programmers need to just add up a bunch of prices on an invoice.

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.

## Related Discussions

Discussion Overview
 group golang-nuts categories go posted Dec 29, '13 at 11:38p active Jan 1, '14 at 4:29p posts 18 users 11 website golang.org

### 11 users in discussion

Content

People

Support

Translate

site design / logo © 2021 Grokbase