pharo-users@lists.pharo.org

Any question about pharo is welcome

View all threads

Silly question about storing and displaying currency amounts?

DP
David Pennington
Mon, Aug 30, 2021 12:02 PM

Hi everyone. I have a little bank analysis package for my own use but having trouble displaying and storing amounts. I parse out a CSV file from the bank and convert the amounts from text to ScaledDecimal. I then store these into a STON file, which converts them back to text. I then read them in and convert them back to ScaledDecimal again.

I am not used to ~Pharo have spent 24 years using VisualAge Smalltalk so I need a little bit of help because I am getting 1 Penny errors in the conversions. I can cope with this but I would like to get it right.

Can anyone give me a simple means of managing, say, an amount like £76.49 from the bank so that it stops coming back to me as £76.48?

David
Totally Objects

Hi everyone. I have a little bank analysis package for my own use but having trouble displaying and storing amounts. I parse out a CSV file from the bank and convert the amounts from text to ScaledDecimal. I then store these into a STON file, which converts them back to text. I then read them in and convert them back to ScaledDecimal again. I am not used to ~Pharo have spent 24 years using VisualAge Smalltalk so I need a little bit of help because I am getting 1 Penny errors in the conversions. I can cope with this but I would like to get it right. Can anyone give me a simple means of managing, say, an amount like £76.49 from the bank so that it stops coming back to me as £76.48? David Totally Objects
SV
Sven Van Caekenberghe
Mon, Aug 30, 2021 12:31 PM

David,

On 30 Aug 2021, at 14:02, David Pennington david@totallyobjects.com wrote:

Hi everyone. I have a little bank analysis package for my own use but having trouble displaying and storing amounts. I parse out a CSV file from the bank and convert the amounts from text to ScaledDecimal. I then store these into a STON file, which converts them back to text. I then read them in and convert them back to ScaledDecimal again.

I am not used to ~Pharo have spent 24 years using VisualAge Smalltalk so I need a little bit of help because I am getting 1 Penny errors in the conversions. I can cope with this but I would like to get it right.

Can anyone give me a simple means of managing, say, an amount like £76.49 from the bank so that it stops coming back to me as £76.48?

David
Totally Objects

Working with money is always challenging. I know that many people say 'Use ScaledDecimal' as if that magically solves all problems but it does not. ScaledDecimal is a bit of a dangerous class to use. It is just a fraction with a certain precision. Internally it might be pretty accurate with respect to most operations, its external representation as floating point number can be misleading, as this representation is prone to all problems related to floating point (including the fact that decimal and binary floating point are not the same).

STON does not doing anything wrong as far as I know. Consider the following:

| amount ston |
amount := 76.49 asScaledDecimal.
ston := STON toString: amount.
STON fromString: ston.
(STON fromString: ston) = amount.
"true"

| amount ston |
amount := 76.49 asScaledDecimal: 2.
ston := STON toString: amount.
STON fromString: ston.
(STON fromString: ston) = amount.
"true"

| amount ston |
amount := 76.49.
ston := STON toString: amount.
STON fromString: ston.
(STON fromString: ston) = amount.
"true"

BUT, 76.49 asScaledDecimal already has your penny loss (if rounded to pennies).

HTH,

Sven

David, > On 30 Aug 2021, at 14:02, David Pennington <david@totallyobjects.com> wrote: > > Hi everyone. I have a little bank analysis package for my own use but having trouble displaying and storing amounts. I parse out a CSV file from the bank and convert the amounts from text to ScaledDecimal. I then store these into a STON file, which converts them back to text. I then read them in and convert them back to ScaledDecimal again. > > I am not used to ~Pharo have spent 24 years using VisualAge Smalltalk so I need a little bit of help because I am getting 1 Penny errors in the conversions. I can cope with this but I would like to get it right. > > Can anyone give me a simple means of managing, say, an amount like £76.49 from the bank so that it stops coming back to me as £76.48? > > David > Totally Objects Working with money is always challenging. I know that many people say 'Use ScaledDecimal' as if that magically solves all problems but it does not. ScaledDecimal is a bit of a dangerous class to use. It is just a fraction with a certain precision. Internally it might be pretty accurate with respect to most operations, its external representation as floating point number can be misleading, as this representation is prone to all problems related to floating point (including the fact that decimal and binary floating point are not the same). STON does not doing anything wrong as far as I know. Consider the following: | amount ston | amount := 76.49 asScaledDecimal. ston := STON toString: amount. STON fromString: ston. (STON fromString: ston) = amount. "true" | amount ston | amount := 76.49 asScaledDecimal: 2. ston := STON toString: amount. STON fromString: ston. (STON fromString: ston) = amount. "true" | amount ston | amount := 76.49. ston := STON toString: amount. STON fromString: ston. (STON fromString: ston) = amount. "true" BUT, 76.49 asScaledDecimal already has your penny loss (if rounded to pennies). HTH, Sven
EL
Esteban Lorenzano
Mon, Aug 30, 2021 12:50 PM

hi,

some time ago there was a "money" package around, that basically had a Currency type that internally stored values as integers (like, 42.0 was becoming 4200). This had some advantages to make this kind of calculus (also, it has the "other" advantage of making you believe that you have a lot more money than what you have ;).
maybe you need to go that direction?
Esteban
On Aug 30 2021, at 2:31 pm, Sven Van Caekenberghe sven@stfx.eu wrote:

David,

On 30 Aug 2021, at 14:02, David Pennington david@totallyobjects.com wrote:

Hi everyone. I have a little bank analysis package for my own use but having trouble displaying and storing amounts. I parse out a CSV file from the bank and convert the amounts from text to ScaledDecimal. I then store these into a STON file, which converts them back to text. I then read them in and convert them back to ScaledDecimal again.

I am not used to ~Pharo have spent 24 years using VisualAge Smalltalk so I need a little bit of help because I am getting 1 Penny errors in the conversions. I can cope with this but I would like to get it right.

Can anyone give me a simple means of managing, say, an amount like £76.49 from the bank so that it stops coming back to me as £76.48?

David
Totally Objects

Working with money is always challenging. I know that many people say 'Use ScaledDecimal' as if that magically solves all problems but it does not. ScaledDecimal is a bit of a dangerous class to use. It is just a fraction with a certain precision. Internally it might be pretty accurate with respect to most operations, its external representation as floating point number can be misleading, as this representation is prone to all problems related to floating point (including the fact that decimal and binary floating point are not the same).
STON does not doing anything wrong as far as I know. Consider the following:
| amount ston |
amount := 76.49 asScaledDecimal.
ston := STON toString: amount.
STON fromString: ston.
(STON fromString: ston) = amount.
"true"

| amount ston |
amount := 76.49 asScaledDecimal: 2.
ston := STON toString: amount.
STON fromString: ston.
(STON fromString: ston) = amount.
"true"

| amount ston |
amount := 76.49.
ston := STON toString: amount.
STON fromString: ston.
(STON fromString: ston) = amount.
"true"

BUT, 76.49 asScaledDecimal already has your penny loss (if rounded to pennies).
HTH,
Sven

hi, some time ago there was a "money" package around, that basically had a Currency type that internally stored values as integers (like, 42.0 was becoming 4200). This had some advantages to make this kind of calculus (also, it has the "other" advantage of making you believe that you have a lot more money than what you have ;). maybe you need to go that direction? Esteban On Aug 30 2021, at 2:31 pm, Sven Van Caekenberghe <sven@stfx.eu> wrote: > David, > > > On 30 Aug 2021, at 14:02, David Pennington <david@totallyobjects.com> wrote: > > > > Hi everyone. I have a little bank analysis package for my own use but having trouble displaying and storing amounts. I parse out a CSV file from the bank and convert the amounts from text to ScaledDecimal. I then store these into a STON file, which converts them back to text. I then read them in and convert them back to ScaledDecimal again. > > > > I am not used to ~Pharo have spent 24 years using VisualAge Smalltalk so I need a little bit of help because I am getting 1 Penny errors in the conversions. I can cope with this but I would like to get it right. > > > > Can anyone give me a simple means of managing, say, an amount like £76.49 from the bank so that it stops coming back to me as £76.48? > > > > David > > Totally Objects > > Working with money is always challenging. I know that many people say 'Use ScaledDecimal' as if that magically solves all problems but it does not. ScaledDecimal is a bit of a dangerous class to use. It is just a fraction with a certain precision. Internally it might be pretty accurate with respect to most operations, its external representation as floating point number can be misleading, as this representation is prone to all problems related to floating point (including the fact that decimal and binary floating point are not the same). > STON does not doing anything wrong as far as I know. Consider the following: > | amount ston | > amount := 76.49 asScaledDecimal. > ston := STON toString: amount. > STON fromString: ston. > (STON fromString: ston) = amount. > "true" > > | amount ston | > amount := 76.49 asScaledDecimal: 2. > ston := STON toString: amount. > STON fromString: ston. > (STON fromString: ston) = amount. > "true" > > | amount ston | > amount := 76.49. > ston := STON toString: amount. > STON fromString: ston. > (STON fromString: ston) = amount. > "true" > > BUT, 76.49 asScaledDecimal already has your penny loss (if rounded to pennies). > HTH, > Sven
J
jtuchel@objektfabrik.de
Mon, Aug 30, 2021 12:51 PM

Hi Sven,

I just tried 46.79 asScaledDecimal and 46.79 asScaledDecimal: 2 in both
VAST and Pharo and see quite different results.
In VAST, not providing a scale returns 46.79, but with a scale of 14
(46.79s14). But it is still 46.79.

What's good is that the results of "asScaledDecimal: 2" yields the same
results on VAST and Pharo.

Your examples also use a fixed scale of 2. So is it safe to assume that
when you provide the scale, ScaledDecimal is good for monetary amounts
in Pharo? I ask because that is what I once learned in an IBM training
decades ago: use ScaledDecimals for money and percentages, never use floats.

Would you agree that as a rule of thumb, Pounds, Dollars and Euros are
safely stored and processed when you make sure to always provide the
scale of 2 (unless you manage stock or petrol prices which use 3 or 4 or
even more digits)?

Joachim

Am 30.08.21 um 14:31 schrieb Sven Van Caekenberghe:

David,

On 30 Aug 2021, at 14:02, David Pennington david@totallyobjects.com wrote:

Hi everyone. I have a little bank analysis package for my own use but having trouble displaying and storing amounts. I parse out a CSV file from the bank and convert the amounts from text to ScaledDecimal. I then store these into a STON file, which converts them back to text. I then read them in and convert them back to ScaledDecimal again.

I am not used to ~Pharo have spent 24 years using VisualAge Smalltalk so I need a little bit of help because I am getting 1 Penny errors in the conversions. I can cope with this but I would like to get it right.

Can anyone give me a simple means of managing, say, an amount like £76.49 from the bank so that it stops coming back to me as £76.48?

David
Totally Objects

Working with money is always challenging. I know that many people say 'Use ScaledDecimal' as if that magically solves all problems but it does not. ScaledDecimal is a bit of a dangerous class to use. It is just a fraction with a certain precision. Internally it might be pretty accurate with respect to most operations, its external representation as floating point number can be misleading, as this representation is prone to all problems related to floating point (including the fact that decimal and binary floating point are not the same).

STON does not doing anything wrong as far as I know. Consider the following:

| amount ston |
amount := 76.49 asScaledDecimal.
ston := STON toString: amount.
STON fromString: ston.
(STON fromString: ston) = amount.
"true"

| amount ston |
amount := 76.49 asScaledDecimal: 2.
ston := STON toString: amount.
STON fromString: ston.
(STON fromString: ston) = amount.
"true"

| amount ston |
amount := 76.49.
ston := STON toString: amount.
STON fromString: ston.
(STON fromString: ston) = amount.
"true"

BUT, 76.49 asScaledDecimal already has your penny loss (if rounded to pennies).

HTH,

Sven

--

Objektfabrik Joachim Tuchel          mailto:jtuchel@objektfabrik.de
Fliederweg 1                        http://www.objektfabrik.de
D-71640 Ludwigsburg                  http://joachimtuchel.wordpress.com
Telefon: +49 7141 56 10 86 0        Fax: +49 7141 56 10 86 1

Hi Sven, I just tried 46.79 asScaledDecimal and 46.79 asScaledDecimal: 2 in both VAST and Pharo and see quite different results. In VAST, not providing a scale returns 46.79, but with a scale of 14 (46.79s14). But it is still 46.79. What's good is that the results of "asScaledDecimal: 2" yields the same results on VAST and Pharo. Your examples also use a fixed scale of 2. So is it safe to assume that when you provide the scale, ScaledDecimal is good for monetary amounts in Pharo? I ask because that is what I once learned in an IBM training decades ago: use ScaledDecimals for money and percentages, never use floats. Would you agree that as a rule of thumb, Pounds, Dollars and Euros are safely stored and processed when you make sure to always provide the scale of 2 (unless you manage stock or petrol prices which use 3 or 4 or even more digits)? Joachim Am 30.08.21 um 14:31 schrieb Sven Van Caekenberghe: > David, > >> On 30 Aug 2021, at 14:02, David Pennington <david@totallyobjects.com> wrote: >> >> Hi everyone. I have a little bank analysis package for my own use but having trouble displaying and storing amounts. I parse out a CSV file from the bank and convert the amounts from text to ScaledDecimal. I then store these into a STON file, which converts them back to text. I then read them in and convert them back to ScaledDecimal again. >> >> I am not used to ~Pharo have spent 24 years using VisualAge Smalltalk so I need a little bit of help because I am getting 1 Penny errors in the conversions. I can cope with this but I would like to get it right. >> >> Can anyone give me a simple means of managing, say, an amount like £76.49 from the bank so that it stops coming back to me as £76.48? >> >> David >> Totally Objects > Working with money is always challenging. I know that many people say 'Use ScaledDecimal' as if that magically solves all problems but it does not. ScaledDecimal is a bit of a dangerous class to use. It is just a fraction with a certain precision. Internally it might be pretty accurate with respect to most operations, its external representation as floating point number can be misleading, as this representation is prone to all problems related to floating point (including the fact that decimal and binary floating point are not the same). > > STON does not doing anything wrong as far as I know. Consider the following: > > | amount ston | > amount := 76.49 asScaledDecimal. > ston := STON toString: amount. > STON fromString: ston. > (STON fromString: ston) = amount. > "true" > > | amount ston | > amount := 76.49 asScaledDecimal: 2. > ston := STON toString: amount. > STON fromString: ston. > (STON fromString: ston) = amount. > "true" > > | amount ston | > amount := 76.49. > ston := STON toString: amount. > STON fromString: ston. > (STON fromString: ston) = amount. > "true" > > BUT, 76.49 asScaledDecimal already has your penny loss (if rounded to pennies). > > HTH, > > Sven > -- ----------------------------------------------------------------------- Objektfabrik Joachim Tuchel mailto:jtuchel@objektfabrik.de Fliederweg 1 http://www.objektfabrik.de D-71640 Ludwigsburg http://joachimtuchel.wordpress.com Telefon: +49 7141 56 10 86 0 Fax: +49 7141 56 10 86 1
SM
Sabine Manaa
Mon, Aug 30, 2021 12:56 PM

Hi Sven,

I just tried 46.79 asScaledDecimal and 46.79 asScaledDecimal: 2 in both
VAST and Pharo and see quite different results.
In VAST, not providing a scale returns 46.79, but with a scale of 14
(46.79s14). But it is still 46.79.

What's good is that the results of "asScaledDecimal: 2" yields the same
results on VAST and Pharo.

Your examples also use a fixed scale of 2. So is it safe to assume that
when you provide the scale, ScaledDecimal is good for monetary amounts
in Pharo? I ask because that is what I once learned in an IBM training
decades ago: use ScaledDecimals for money and percentages, never use
floats.

Would you agree that as a rule of thumb, Pounds, Dollars and Euros are
safely stored and processed when you make sure to always provide the
scale of 2 (unless you manage stock or petrol prices which use 3 or 4 or
even more digits)?

Joachim

Am 30.08.21 um 14:31 schrieb Sven Van Caekenberghe:

David,

On 30 Aug 2021, at 14:02, David Pennington david@totallyobjects.com

wrote:

Hi everyone. I have a little bank analysis package for my own use but

having trouble displaying and storing amounts. I parse out a CSV file from
the bank and convert the amounts from text to ScaledDecimal. I then store
these into a STON file, which converts them back to text. I then read them
in and convert them back to ScaledDecimal again.

I am not used to ~Pharo have spent 24 years using VisualAge Smalltalk

so I need a little bit of help because I am getting 1 Penny errors in the
conversions. I can cope with this but I would like to get it right.

Can anyone give me a simple means of managing, say, an amount like

£76.49 from the bank so that it stops coming back to me as £76.48?

David
Totally Objects

Working with money is always challenging. I know that many people say

'Use ScaledDecimal' as if that magically solves all problems but it does
not. ScaledDecimal is a bit of a dangerous class to use. It is just a
fraction with a certain precision. Internally it might be pretty accurate
with respect to most operations, its external representation as floating
point number can be misleading, as this representation is prone to all
problems related to floating point (including the fact that decimal and
binary floating point are not the same).

STON does not doing anything wrong as far as I know. Consider the

following:

| amount ston |
amount := 76.49 asScaledDecimal.
ston := STON toString: amount.
STON fromString: ston.
(STON fromString: ston) = amount.
"true"

| amount ston |
amount := 76.49 asScaledDecimal: 2.
ston := STON toString: amount.
STON fromString: ston.
(STON fromString: ston) = amount.
"true"

| amount ston |
amount := 76.49.
ston := STON toString: amount.
STON fromString: ston.
(STON fromString: ston) = amount.
"true"

BUT, 76.49 asScaledDecimal already has your penny loss (if rounded to

pennies).

HTH,

Sven

--

Objektfabrik Joachim Tuchel          mailto:jtuchel@objektfabrik.de
Fliederweg 1                        http://www.objektfabrik.de
D-71640 Ludwigsburg                  http://joachimtuchel.wordpress.com
Telefon: +49 7141 56 10 86 0        Fax: +49 7141 56 10 86 1

http://smalltalkhub.com/pdebruic/Money/index.html Am Mo., 30. Aug. 2021 um 14:51 Uhr schrieb jtuchel@objektfabrik.de < jtuchel@objektfabrik.de>: > Hi Sven, > > > I just tried 46.79 asScaledDecimal and 46.79 asScaledDecimal: 2 in both > VAST and Pharo and see quite different results. > In VAST, not providing a scale returns 46.79, but with a scale of 14 > (46.79s14). But it is still 46.79. > > What's good is that the results of "asScaledDecimal: 2" yields the same > results on VAST and Pharo. > > Your examples also use a fixed scale of 2. So is it safe to assume that > when you provide the scale, ScaledDecimal is good for monetary amounts > in Pharo? I ask because that is what I once learned in an IBM training > decades ago: use ScaledDecimals for money and percentages, never use > floats. > > Would you agree that as a rule of thumb, Pounds, Dollars and Euros are > safely stored and processed when you make sure to always provide the > scale of 2 (unless you manage stock or petrol prices which use 3 or 4 or > even more digits)? > > Joachim > > > > > > Am 30.08.21 um 14:31 schrieb Sven Van Caekenberghe: > > David, > > > >> On 30 Aug 2021, at 14:02, David Pennington <david@totallyobjects.com> > wrote: > >> > >> Hi everyone. I have a little bank analysis package for my own use but > having trouble displaying and storing amounts. I parse out a CSV file from > the bank and convert the amounts from text to ScaledDecimal. I then store > these into a STON file, which converts them back to text. I then read them > in and convert them back to ScaledDecimal again. > >> > >> I am not used to ~Pharo have spent 24 years using VisualAge Smalltalk > so I need a little bit of help because I am getting 1 Penny errors in the > conversions. I can cope with this but I would like to get it right. > >> > >> Can anyone give me a simple means of managing, say, an amount like > £76.49 from the bank so that it stops coming back to me as £76.48? > >> > >> David > >> Totally Objects > > Working with money is always challenging. I know that many people say > 'Use ScaledDecimal' as if that magically solves all problems but it does > not. ScaledDecimal is a bit of a dangerous class to use. It is just a > fraction with a certain precision. Internally it might be pretty accurate > with respect to most operations, its external representation as floating > point number can be misleading, as this representation is prone to all > problems related to floating point (including the fact that decimal and > binary floating point are not the same). > > > > STON does not doing anything wrong as far as I know. Consider the > following: > > > > | amount ston | > > amount := 76.49 asScaledDecimal. > > ston := STON toString: amount. > > STON fromString: ston. > > (STON fromString: ston) = amount. > > "true" > > > > | amount ston | > > amount := 76.49 asScaledDecimal: 2. > > ston := STON toString: amount. > > STON fromString: ston. > > (STON fromString: ston) = amount. > > "true" > > > > | amount ston | > > amount := 76.49. > > ston := STON toString: amount. > > STON fromString: ston. > > (STON fromString: ston) = amount. > > "true" > > > > BUT, 76.49 asScaledDecimal already has your penny loss (if rounded to > pennies). > > > > HTH, > > > > Sven > > > > -- > ----------------------------------------------------------------------- > Objektfabrik Joachim Tuchel mailto:jtuchel@objektfabrik.de > Fliederweg 1 http://www.objektfabrik.de > D-71640 Ludwigsburg http://joachimtuchel.wordpress.com > Telefon: +49 7141 56 10 86 0 Fax: +49 7141 56 10 86 1 > >
DP
David Pennington
Mon, Aug 30, 2021 1:01 PM

I come from a currency trader background and way back in 1983, I was dealing with this in North Star Basic and then UCSD Pascal  and into VisualSmalltalk (remember that?) so I have some history here. Trouble is, at 76, my little grey cells are letting me down bit. Excuses over. I will go back into the code and make sure that I scale all these ScaledDecimals to 2 and see if that helps.

BTW, I wasn’t suggesting that there was any problem with STON as that works brilliantly for me.

David

On 30 Aug 2021, at 13:51, jtuchel@objektfabrik.de wrote:

Hi Sven,

I just tried 46.79 asScaledDecimal and 46.79 asScaledDecimal: 2 in both VAST and Pharo and see quite different results.
In VAST, not providing a scale returns 46.79, but with a scale of 14 (46.79s14). But it is still 46.79.

What's good is that the results of "asScaledDecimal: 2" yields the same results on VAST and Pharo.

Your examples also use a fixed scale of 2. So is it safe to assume that when you provide the scale, ScaledDecimal is good for monetary amounts in Pharo? I ask because that is what I once learned in an IBM training decades ago: use ScaledDecimals for money and percentages, never use floats.

Would you agree that as a rule of thumb, Pounds, Dollars and Euros are safely stored and processed when you make sure to always provide the scale of 2 (unless you manage stock or petrol prices which use 3 or 4 or even more digits)?

Joachim

Am 30.08.21 um 14:31 schrieb Sven Van Caekenberghe:

David,

On 30 Aug 2021, at 14:02, David Pennington david@totallyobjects.com wrote:

Hi everyone. I have a little bank analysis package for my own use but having trouble displaying and storing amounts. I parse out a CSV file from the bank and convert the amounts from text to ScaledDecimal. I then store these into a STON file, which converts them back to text. I then read them in and convert them back to ScaledDecimal again.

I am not used to ~Pharo have spent 24 years using VisualAge Smalltalk so I need a little bit of help because I am getting 1 Penny errors in the conversions. I can cope with this but I would like to get it right.

Can anyone give me a simple means of managing, say, an amount like £76.49 from the bank so that it stops coming back to me as £76.48?

David
Totally Objects

Working with money is always challenging. I know that many people say 'Use ScaledDecimal' as if that magically solves all problems but it does not. ScaledDecimal is a bit of a dangerous class to use. It is just a fraction with a certain precision. Internally it might be pretty accurate with respect to most operations, its external representation as floating point number can be misleading, as this representation is prone to all problems related to floating point (including the fact that decimal and binary floating point are not the same).

STON does not doing anything wrong as far as I know. Consider the following:

| amount ston |
amount := 76.49 asScaledDecimal.
ston := STON toString: amount.
STON fromString: ston.
(STON fromString: ston) = amount.
"true"

| amount ston |
amount := 76.49 asScaledDecimal: 2.
ston := STON toString: amount.
STON fromString: ston.
(STON fromString: ston) = amount.
"true"

| amount ston |
amount := 76.49.
ston := STON toString: amount.
STON fromString: ston.
(STON fromString: ston) = amount.
"true"

BUT, 76.49 asScaledDecimal already has your penny loss (if rounded to pennies).

HTH,

Sven

--

Objektfabrik Joachim Tuchel          mailto:jtuchel@objektfabrik.de
Fliederweg 1                        http://www.objektfabrik.de
D-71640 Ludwigsburg                  http://joachimtuchel.wordpress.com
Telefon: +49 7141 56 10 86 0        Fax: +49 7141 56 10 86 1

I come from a currency trader background and way back in 1983, I was dealing with this in North Star Basic and then UCSD Pascal and into VisualSmalltalk (remember that?) so I have some history here. Trouble is, at 76, my little grey cells are letting me down bit. Excuses over. I will go back into the code and make sure that I scale all these ScaledDecimals to 2 and see if that helps. BTW, I wasn’t suggesting that there was any problem with STON as that works brilliantly for me. David > On 30 Aug 2021, at 13:51, jtuchel@objektfabrik.de wrote: > > Hi Sven, > > > I just tried 46.79 asScaledDecimal and 46.79 asScaledDecimal: 2 in both VAST and Pharo and see quite different results. > In VAST, not providing a scale returns 46.79, but with a scale of 14 (46.79s14). But it is still 46.79. > > What's good is that the results of "asScaledDecimal: 2" yields the same results on VAST and Pharo. > > Your examples also use a fixed scale of 2. So is it safe to assume that when you provide the scale, ScaledDecimal is good for monetary amounts in Pharo? I ask because that is what I once learned in an IBM training decades ago: use ScaledDecimals for money and percentages, never use floats. > > Would you agree that as a rule of thumb, Pounds, Dollars and Euros are safely stored and processed when you make sure to always provide the scale of 2 (unless you manage stock or petrol prices which use 3 or 4 or even more digits)? > > Joachim > > > > > > Am 30.08.21 um 14:31 schrieb Sven Van Caekenberghe: >> David, >> >>> On 30 Aug 2021, at 14:02, David Pennington <david@totallyobjects.com> wrote: >>> >>> Hi everyone. I have a little bank analysis package for my own use but having trouble displaying and storing amounts. I parse out a CSV file from the bank and convert the amounts from text to ScaledDecimal. I then store these into a STON file, which converts them back to text. I then read them in and convert them back to ScaledDecimal again. >>> >>> I am not used to ~Pharo have spent 24 years using VisualAge Smalltalk so I need a little bit of help because I am getting 1 Penny errors in the conversions. I can cope with this but I would like to get it right. >>> >>> Can anyone give me a simple means of managing, say, an amount like £76.49 from the bank so that it stops coming back to me as £76.48? >>> >>> David >>> Totally Objects >> Working with money is always challenging. I know that many people say 'Use ScaledDecimal' as if that magically solves all problems but it does not. ScaledDecimal is a bit of a dangerous class to use. It is just a fraction with a certain precision. Internally it might be pretty accurate with respect to most operations, its external representation as floating point number can be misleading, as this representation is prone to all problems related to floating point (including the fact that decimal and binary floating point are not the same). >> >> STON does not doing anything wrong as far as I know. Consider the following: >> >> | amount ston | >> amount := 76.49 asScaledDecimal. >> ston := STON toString: amount. >> STON fromString: ston. >> (STON fromString: ston) = amount. >> "true" >> >> | amount ston | >> amount := 76.49 asScaledDecimal: 2. >> ston := STON toString: amount. >> STON fromString: ston. >> (STON fromString: ston) = amount. >> "true" >> >> | amount ston | >> amount := 76.49. >> ston := STON toString: amount. >> STON fromString: ston. >> (STON fromString: ston) = amount. >> "true" >> >> BUT, 76.49 asScaledDecimal already has your penny loss (if rounded to pennies). >> >> HTH, >> >> Sven >> > > -- > ----------------------------------------------------------------------- > Objektfabrik Joachim Tuchel mailto:jtuchel@objektfabrik.de > Fliederweg 1 http://www.objektfabrik.de > D-71640 Ludwigsburg http://joachimtuchel.wordpress.com > Telefon: +49 7141 56 10 86 0 Fax: +49 7141 56 10 86 1 >
EM
Esteban Maringolo
Mon, Aug 30, 2021 1:38 PM

I was recently bitten by this wrong "scaled decimal expectation", in
which what I thought was wrong it actually wasn't, or I can't tell
whether it was.

I would expect that a scaled decimal would be something like what
Esteban L. suggests, an integer where you just move the decimal point
for printing, and also a number where you lose precision due to
truncation.

So this: ((1.0s2 / 3) * 3) + 0.01s2
Would yield 1 instead of "1.01s2"

So if you use the "integer only" representation, it is very much like
any currency number would me managed:
((100 / 3) truncated * 3 + 1) / 100

This, of course, yields the right value, but it started truncated from
the beginning.
(0.33s2 * 3) + 0.01s2 "1"

I would appreciate any pointers about learning more about this.
It's embarrassing for me not knowing how each type should work in
order to tell what's right from what's wrong.

Regards!

ps: In my case this wasn't because of money, but another kind of use,
but the situation is the same.

Esteban A. Maringolo

On Mon, Aug 30, 2021 at 9:51 AM Esteban Lorenzano estebanlm@netc.eu wrote:

hi,

some time ago there was a "money" package around, that basically had a Currency type that internally stored values as integers (like, 42.0 was becoming 4200). This had some advantages to make this kind of calculus (also, it has the "other" advantage of making you believe that you have a lot more money than what you have ;).

maybe you need to go that direction?

Esteban

On Aug 30 2021, at 2:31 pm, Sven Van Caekenberghe sven@stfx.eu wrote:

David,

On 30 Aug 2021, at 14:02, David Pennington david@totallyobjects.com wrote:

Hi everyone. I have a little bank analysis package for my own use but having trouble displaying and storing amounts. I parse out a CSV file from the bank and convert the amounts from text to ScaledDecimal. I then store these into a STON file, which converts them back to text. I then read them in and convert them back to ScaledDecimal again.

I am not used to ~Pharo have spent 24 years using VisualAge Smalltalk so I need a little bit of help because I am getting 1 Penny errors in the conversions. I can cope with this but I would like to get it right.

Can anyone give me a simple means of managing, say, an amount like £76.49 from the bank so that it stops coming back to me as £76.48?

David
Totally Objects

Working with money is always challenging. I know that many people say 'Use ScaledDecimal' as if that magically solves all problems but it does not. ScaledDecimal is a bit of a dangerous class to use. It is just a fraction with a certain precision. Internally it might be pretty accurate with respect to most operations, its external representation as floating point number can be misleading, as this representation is prone to all problems related to floating point (including the fact that decimal and binary floating point are not the same).

STON does not doing anything wrong as far as I know. Consider the following:

| amount ston |
amount := 76.49 asScaledDecimal.
ston := STON toString: amount.
STON fromString: ston.
(STON fromString: ston) = amount.
"true"

| amount ston |
amount := 76.49 asScaledDecimal: 2.
ston := STON toString: amount.
STON fromString: ston.
(STON fromString: ston) = amount.
"true"

| amount ston |
amount := 76.49.
ston := STON toString: amount.
STON fromString: ston.
(STON fromString: ston) = amount.
"true"

BUT, 76.49 asScaledDecimal already has your penny loss (if rounded to pennies).

HTH,

Sven

I was recently bitten by this wrong "scaled decimal expectation", in which what I thought was wrong it actually wasn't, or I can't tell whether it was. I would expect that a scaled decimal would be something like what Esteban L. suggests, an integer where you just move the decimal point for printing, and also a number where you lose precision due to truncation. So this: ((1.0s2 / 3) * 3) + 0.01s2 Would yield 1 instead of "1.01s2" So if you use the "integer only" representation, it is very much like any currency number would me managed: ((100 / 3) truncated * 3 + 1) / 100 This, of course, yields the right value, but it started truncated from the beginning. (0.33s2 * 3) + 0.01s2 "1" I would appreciate any pointers about learning more about this. It's embarrassing for me not knowing how each type should work in order to tell what's right from what's wrong. Regards! ps: In my case this wasn't because of money, but another kind of use, but the situation is the same. Esteban A. Maringolo On Mon, Aug 30, 2021 at 9:51 AM Esteban Lorenzano <estebanlm@netc.eu> wrote: > > hi, > > some time ago there was a "money" package around, that basically had a Currency type that internally stored values as integers (like, 42.0 was becoming 4200). This had some advantages to make this kind of calculus (also, it has the "other" advantage of making you believe that you have a lot more money than what you have ;). > > maybe you need to go that direction? > > Esteban > > On Aug 30 2021, at 2:31 pm, Sven Van Caekenberghe <sven@stfx.eu> wrote: > > David, > > > On 30 Aug 2021, at 14:02, David Pennington <david@totallyobjects.com> wrote: > > > > Hi everyone. I have a little bank analysis package for my own use but having trouble displaying and storing amounts. I parse out a CSV file from the bank and convert the amounts from text to ScaledDecimal. I then store these into a STON file, which converts them back to text. I then read them in and convert them back to ScaledDecimal again. > > > > I am not used to ~Pharo have spent 24 years using VisualAge Smalltalk so I need a little bit of help because I am getting 1 Penny errors in the conversions. I can cope with this but I would like to get it right. > > > > Can anyone give me a simple means of managing, say, an amount like £76.49 from the bank so that it stops coming back to me as £76.48? > > > > David > > Totally Objects > > Working with money is always challenging. I know that many people say 'Use ScaledDecimal' as if that magically solves all problems but it does not. ScaledDecimal is a bit of a dangerous class to use. It is just a fraction with a certain precision. Internally it might be pretty accurate with respect to most operations, its external representation as floating point number can be misleading, as this representation is prone to all problems related to floating point (including the fact that decimal and binary floating point are not the same). > > STON does not doing anything wrong as far as I know. Consider the following: > > | amount ston | > amount := 76.49 asScaledDecimal. > ston := STON toString: amount. > STON fromString: ston. > (STON fromString: ston) = amount. > "true" > > | amount ston | > amount := 76.49 asScaledDecimal: 2. > ston := STON toString: amount. > STON fromString: ston. > (STON fromString: ston) = amount. > "true" > > | amount ston | > amount := 76.49. > ston := STON toString: amount. > STON fromString: ston. > (STON fromString: ston) = amount. > "true" > > BUT, 76.49 asScaledDecimal already has your penny loss (if rounded to pennies). > > HTH, > > Sven
RO
Richard O'Keefe
Mon, Aug 30, 2021 10:58 PM

Ah, you have run into the insufficiently well known
"ScaledDecimal looks like what you need but isn't".

In VisualAge, you have a data type that is basically a reflection of iBM
mainframe "packed decimal" format, and perfectly suits the needs of
an SQL or COBOL interface.  It gives you round-tripping with no error.

In my Smalltalk, ScaledDecimal is a pair (n,s) where n and s are
unrestricted integers, representing n * (10 raisedTo: s).  This also
gives you exact round-tripping and suits the needs of an SQL or COBOL
interface.

However, in Squeak and Pharo, ScaledDecimal is something else
entirely.  Basically, a pair (q,s) where q is an Integer or Fraction,
and s is a scale factor used for printing. This doesn't just lead to
oddities like two unequal ScaledDecimals printing identically, it
leads to rounding issues. This is not a bug, it is ScaledDecimal working
as designed.

Working within Squeak, the simplest approach is to represent money as
pence, and the next simplest is to make or find a Money class.

On Tue, 31 Aug 2021 at 00:02, David Pennington david@totallyobjects.com wrote:

Hi everyone. I have a little bank analysis package for my own use but having trouble displaying and storing amounts. I parse out a CSV file from the bank and convert the amounts from text to ScaledDecimal. I then store these into a STON file, which converts them back to text. I then read them in and convert them back to ScaledDecimal again.

I am not used to ~Pharo have spent 24 years using VisualAge Smalltalk so I need a little bit of help because I am getting 1 Penny errors in the conversions. I can cope with this but I would like to get it right.

Can anyone give me a simple means of managing, say, an amount like £76.49 from the bank so that it stops coming back to me as £76.48?

David
Totally Objects

Ah, you have run into the insufficiently well known "ScaledDecimal looks like what you need but isn't". In VisualAge, you have a data type that is basically a reflection of iBM mainframe "packed decimal" format, and perfectly suits the needs of an SQL or COBOL interface. It gives you round-tripping with no error. In my Smalltalk, ScaledDecimal is a pair (n,s) where n and s are unrestricted integers, representing n * (10 raisedTo: s). This also gives you exact round-tripping and suits the needs of an SQL or COBOL interface. However, in Squeak and Pharo, ScaledDecimal is something else entirely. Basically, a pair (q,s) where q is an Integer or Fraction, and s is a scale factor used for *printing*. This doesn't just lead to oddities like two unequal ScaledDecimals printing identically, it leads to rounding issues. This is not a bug, it is ScaledDecimal working as designed. Working within Squeak, the simplest approach is to represent money as pence, and the next simplest is to make or find a Money class. On Tue, 31 Aug 2021 at 00:02, David Pennington <david@totallyobjects.com> wrote: > > Hi everyone. I have a little bank analysis package for my own use but having trouble displaying and storing amounts. I parse out a CSV file from the bank and convert the amounts from text to ScaledDecimal. I then store these into a STON file, which converts them back to text. I then read them in and convert them back to ScaledDecimal again. > > I am not used to ~Pharo have spent 24 years using VisualAge Smalltalk so I need a little bit of help because I am getting 1 Penny errors in the conversions. I can cope with this but I would like to get it right. > > Can anyone give me a simple means of managing, say, an amount like £76.49 from the bank so that it stops coming back to me as £76.48? > > David > Totally Objects
GP
Guillermo Polito
Tue, Aug 31, 2021 7:43 AM

Hi all,

In the past months I worked a bit with it and found many problems too, like:

I also got hit with “downgrading" issues during my vacation coding. For example, when operating a scaled decimal with a float, the result gets downgraded to a float.
See

17.777 asScaledDecimal + 0.0

From all the comments I understand that the current implementation is not very useful, they all lead to “do not use it, instead do XXX” where XXX is either

  • write your own
  • load that other package
  • use an integer to represent pennies

This this means that either it can be removed, or it can benefit with a new and better implementation.
I think it would be interesting to have a better ScaledDecimal implementation, that not only does precise printing but also precise arithmetics.

Or maybe somebody has a good implementation already available?

Cheers,
Guille

El 31 ago 2021, a las 0:58, Richard O'Keefe raoknz@gmail.com escribió:

Ah, you have run into the insufficiently well known
"ScaledDecimal looks like what you need but isn't".

In VisualAge, you have a data type that is basically a reflection of iBM
mainframe "packed decimal" format, and perfectly suits the needs of
an SQL or COBOL interface.  It gives you round-tripping with no error.

In my Smalltalk, ScaledDecimal is a pair (n,s) where n and s are
unrestricted integers, representing n * (10 raisedTo: s).  This also
gives you exact round-tripping and suits the needs of an SQL or COBOL
interface.

However, in Squeak and Pharo, ScaledDecimal is something else
entirely.  Basically, a pair (q,s) where q is an Integer or Fraction,
and s is a scale factor used for printing. This doesn't just lead to
oddities like two unequal ScaledDecimals printing identically, it
leads to rounding issues. This is not a bug, it is ScaledDecimal working
as designed.

Working within Squeak, the simplest approach is to represent money as
pence, and the next simplest is to make or find a Money class.

On Tue, 31 Aug 2021 at 00:02, David Pennington david@totallyobjects.com wrote:

Hi everyone. I have a little bank analysis package for my own use but having trouble displaying and storing amounts. I parse out a CSV file from the bank and convert the amounts from text to ScaledDecimal. I then store these into a STON file, which converts them back to text. I then read them in and convert them back to ScaledDecimal again.

I am not used to ~Pharo have spent 24 years using VisualAge Smalltalk so I need a little bit of help because I am getting 1 Penny errors in the conversions. I can cope with this but I would like to get it right.

Can anyone give me a simple means of managing, say, an amount like £76.49 from the bank so that it stops coming back to me as £76.48?

David
Totally Objects

Hi all, In the past months I worked a bit with it and found many problems too, like: - doing scaled decimal arithmetics losing precision https://github.com/pharo-project/pharo/issues/8668 - strange default scale values https://github.com/pharo-project/pharo/issues/8669 I also got hit with “downgrading" issues during my vacation coding. For example, when operating a scaled decimal with a float, the result gets downgraded to a float. See 17.777 asScaledDecimal + 0.0 From all the comments I understand that the current implementation is not very useful, they all lead to “do not use it, instead do XXX” where XXX is either - write your own - load that other package - use an integer to represent pennies This this means that either it can be removed, or it can benefit with a new and better implementation. I think it would be interesting to have a better ScaledDecimal implementation, that not only does precise printing but also precise arithmetics. Or maybe somebody has a good implementation already available? Cheers, Guille > El 31 ago 2021, a las 0:58, Richard O'Keefe <raoknz@gmail.com> escribió: > > Ah, you have run into the insufficiently well known > "ScaledDecimal looks like what you need but isn't". > > In VisualAge, you have a data type that is basically a reflection of iBM > mainframe "packed decimal" format, and perfectly suits the needs of > an SQL or COBOL interface. It gives you round-tripping with no error. > > In my Smalltalk, ScaledDecimal is a pair (n,s) where n and s are > unrestricted integers, representing n * (10 raisedTo: s). This also > gives you exact round-tripping and suits the needs of an SQL or COBOL > interface. > > However, in Squeak and Pharo, ScaledDecimal is something else > entirely. Basically, a pair (q,s) where q is an Integer or Fraction, > and s is a scale factor used for *printing*. This doesn't just lead to > oddities like two unequal ScaledDecimals printing identically, it > leads to rounding issues. This is not a bug, it is ScaledDecimal working > as designed. > > Working within Squeak, the simplest approach is to represent money as > pence, and the next simplest is to make or find a Money class. > > On Tue, 31 Aug 2021 at 00:02, David Pennington <david@totallyobjects.com> wrote: >> >> Hi everyone. I have a little bank analysis package for my own use but having trouble displaying and storing amounts. I parse out a CSV file from the bank and convert the amounts from text to ScaledDecimal. I then store these into a STON file, which converts them back to text. I then read them in and convert them back to ScaledDecimal again. >> >> I am not used to ~Pharo have spent 24 years using VisualAge Smalltalk so I need a little bit of help because I am getting 1 Penny errors in the conversions. I can cope with this but I would like to get it right. >> >> Can anyone give me a simple means of managing, say, an amount like £76.49 from the bank so that it stops coming back to me as £76.48? >> >> David >> Totally Objects
RO
Richard O'Keefe
Wed, Sep 1, 2021 4:14 AM

I have
ScaledDecimal, based on the ANSI Smalltalk standard, but
fixed point decimal arithmetic, because that's what the ANSI Smalltalk
standard calls for (citing a non-existent part of the LIA standard) but
contradicts

FixedPoint, a version of that specifically intended for plugging into
Squeak and/or Pharo, the snag being that I don't seem to have kept
the change set, just the master.  I can recreate and donate the
change set if anyone would like it.

PackedDecimal, which just models VisualAge 31-digit packed decimal
for interoperability, but does not do arithmetic.

On Tue, 31 Aug 2021 at 19:44, Guillermo Polito
guillermopolito@gmail.com wrote:

Hi all,

In the past months I worked a bit with it and found many problems too, like:

I also got hit with “downgrading" issues during my vacation coding. For example, when operating a scaled decimal with a float, the result gets downgraded to a float.
See

17.777 asScaledDecimal + 0.0

From all the comments I understand that the current implementation is not very useful, they all lead to “do not use it, instead do XXX” where XXX is either

  • write your own
  • load that other package
  • use an integer to represent pennies

This this means that either it can be removed, or it can benefit with a new and better implementation.
I think it would be interesting to have a better ScaledDecimal implementation, that not only does precise printing but also precise arithmetics.

Or maybe somebody has a good implementation already available?

Cheers,
Guille

El 31 ago 2021, a las 0:58, Richard O'Keefe raoknz@gmail.com escribió:

Ah, you have run into the insufficiently well known
"ScaledDecimal looks like what you need but isn't".

In VisualAge, you have a data type that is basically a reflection of iBM
mainframe "packed decimal" format, and perfectly suits the needs of
an SQL or COBOL interface.  It gives you round-tripping with no error.

In my Smalltalk, ScaledDecimal is a pair (n,s) where n and s are
unrestricted integers, representing n * (10 raisedTo: s).  This also
gives you exact round-tripping and suits the needs of an SQL or COBOL
interface.

However, in Squeak and Pharo, ScaledDecimal is something else
entirely.  Basically, a pair (q,s) where q is an Integer or Fraction,
and s is a scale factor used for printing. This doesn't just lead to
oddities like two unequal ScaledDecimals printing identically, it
leads to rounding issues. This is not a bug, it is ScaledDecimal working
as designed.

Working within Squeak, the simplest approach is to represent money as
pence, and the next simplest is to make or find a Money class.

On Tue, 31 Aug 2021 at 00:02, David Pennington david@totallyobjects.com wrote:

Hi everyone. I have a little bank analysis package for my own use but having trouble displaying and storing amounts. I parse out a CSV file from the bank and convert the amounts from text to ScaledDecimal. I then store these into a STON file, which converts them back to text. I then read them in and convert them back to ScaledDecimal again.

I am not used to ~Pharo have spent 24 years using VisualAge Smalltalk so I need a little bit of help because I am getting 1 Penny errors in the conversions. I can cope with this but I would like to get it right.

Can anyone give me a simple means of managing, say, an amount like £76.49 from the bank so that it stops coming back to me as £76.48?

David
Totally Objects

I have ScaledDecimal, based on the ANSI Smalltalk standard, but fixed point decimal arithmetic, because that's what the ANSI Smalltalk standard calls for (citing a non-existent part of the LIA standard) but contradicts FixedPoint, a version of that specifically intended for plugging into Squeak and/or Pharo, the snag being that I don't seem to have kept the change set, just the master. I can recreate and donate the change set if anyone would like it. PackedDecimal, which just models VisualAge 31-digit packed decimal for interoperability, but does not do arithmetic. On Tue, 31 Aug 2021 at 19:44, Guillermo Polito <guillermopolito@gmail.com> wrote: > > Hi all, > > In the past months I worked a bit with it and found many problems too, like: > - doing scaled decimal arithmetics losing precision > https://github.com/pharo-project/pharo/issues/8668 > - strange default scale values > https://github.com/pharo-project/pharo/issues/8669 > > I also got hit with “downgrading" issues during my vacation coding. For example, when operating a scaled decimal with a float, the result gets downgraded to a float. > See > > 17.777 asScaledDecimal + 0.0 > > From all the comments I understand that the current implementation is not very useful, they all lead to “do not use it, instead do XXX” where XXX is either > - write your own > - load that other package > - use an integer to represent pennies > > This this means that either it can be removed, or it can benefit with a new and better implementation. > I think it would be interesting to have a better ScaledDecimal implementation, that not only does precise printing but also precise arithmetics. > > Or maybe somebody has a good implementation already available? > > Cheers, > Guille > > > El 31 ago 2021, a las 0:58, Richard O'Keefe <raoknz@gmail.com> escribió: > > > > Ah, you have run into the insufficiently well known > > "ScaledDecimal looks like what you need but isn't". > > > > In VisualAge, you have a data type that is basically a reflection of iBM > > mainframe "packed decimal" format, and perfectly suits the needs of > > an SQL or COBOL interface. It gives you round-tripping with no error. > > > > In my Smalltalk, ScaledDecimal is a pair (n,s) where n and s are > > unrestricted integers, representing n * (10 raisedTo: s). This also > > gives you exact round-tripping and suits the needs of an SQL or COBOL > > interface. > > > > However, in Squeak and Pharo, ScaledDecimal is something else > > entirely. Basically, a pair (q,s) where q is an Integer or Fraction, > > and s is a scale factor used for *printing*. This doesn't just lead to > > oddities like two unequal ScaledDecimals printing identically, it > > leads to rounding issues. This is not a bug, it is ScaledDecimal working > > as designed. > > > > Working within Squeak, the simplest approach is to represent money as > > pence, and the next simplest is to make or find a Money class. > > > > On Tue, 31 Aug 2021 at 00:02, David Pennington <david@totallyobjects.com> wrote: > >> > >> Hi everyone. I have a little bank analysis package for my own use but having trouble displaying and storing amounts. I parse out a CSV file from the bank and convert the amounts from text to ScaledDecimal. I then store these into a STON file, which converts them back to text. I then read them in and convert them back to ScaledDecimal again. > >> > >> I am not used to ~Pharo have spent 24 years using VisualAge Smalltalk so I need a little bit of help because I am getting 1 Penny errors in the conversions. I can cope with this but I would like to get it right. > >> > >> Can anyone give me a simple means of managing, say, an amount like £76.49 from the bank so that it stops coming back to me as £76.48? > >> > >> David > >> Totally Objects