Hello everyone, This is an issue I've had awareness of going way back but it's the first time I've had to personally deal with it. I've done some research and found it addressed in a number of ways but given current time pressures and a huge list of to-dos, I thought I'd turn to the community for rapid advice to get me over the hump. The circumstances are summarized below in code and comments suitable for a playground. "This is the actual arithmetic I want to do... 0.09560268 - 0.005 = 0.09060268" "Evaluate this in a playground and you'll see this is what floating point arithmetic produces --the first two are wrong, every one after is correct" 0.09560268 - 0.005 "=> 0.09060267999999999". 0.0956026 - 0.005 "=> 0.09060259999999999". 0.095602 - 0.005 "=> 0.090602". 0.09560 - 0.005 "=> 0.0906". 0.0956 - 0.005 "=> 0.0906". 0.095 - 0.005 "=> 0.09". "This workaround works" 0.09560268 - 0.005 roundTo: 0.00000001 "=> 0.09060268". "but one has to compute number of digits of precision and according to study above, it's not necessary at precisions >= 0.000001" "What are other suggestions, workarounds or approaches community has?" "THANKS!" Don Howard <https://objectguild.com> *Founding Member* dhoward@objectguild.com +31653139744 (US) 651-253-7024
Whats wrong with #roundedTo: ? If you actually need it calculated to 8 significant digits then you can use scaled decimals e.g. (0.09560268 asScaledDecimal - 0.005 asScaledDecimal) see https://0.30000000000000004.com for more about why floating point math does this sometimes Donald Howard wrote
Hello everyone,
This is an issue I've had awareness of going way back but it's the first time I've had to personally deal with it. I've done some research and found it addressed in a number of ways but given current time pressures and a huge list of to-dos, I thought I'd turn to the community for rapid advice to get me over the hump. The circumstances are summarized below in code and comments suitable for a playground.
"This is the actual arithmetic I want to do... 0.09560268 - 0.005 = 0.09060268"
"Evaluate this in a playground and you'll see this is what floating point arithmetic produces --the first two are wrong, every one after is correct" 0.09560268 - 0.005 "=> 0.09060267999999999". 0.0956026 - 0.005 "=> 0.09060259999999999". 0.095602 - 0.005 "=> 0.090602". 0.09560 - 0.005 "=> 0.0906". 0.0956 - 0.005 "=> 0.0906". 0.095 - 0.005 "=> 0.09".
"This workaround works" 0.09560268 - 0.005 roundTo: 0.00000001 "=> 0.09060268". "but one has to compute number of digits of precision and according to study above, it's not necessary at precisions >= 0.000001"
"What are other suggestions, workarounds or approaches community has?" "THANKS!"
Don Howard
<https://objectguild.com> *Founding Member*
dhoward@
+31653139744 (US) 651-253-7024
-- Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html
On 13 Jan 2020, at 00:28, Paul DeBruicker <pdebruic@gmail.com> wrote:
Whats wrong with #roundedTo: ?
If you actually need it calculated to 8 significant digits then you can use scaled decimals e.g.
(0.09560268 asScaledDecimal - 0.005 asScaledDecimal)
The weird thing is though, that is still does not behave 100% as one would expect (i.e. it does not seem exact). 0.09560268 asScaledDecimal - 0.005 asScaledDecimal. "0.09060268s8" 0.09560268 asScaledDecimal - 0.005 asScaledDecimal = 0.09060268 asScaledDecimal. "false" 0.09560268 asScaledDecimal - 0.005 asScaledDecimal = 0.09060268s8. "false" The internal fractions are not the same ... While (9560268 / 1e8) - (5 / 1e3) = (9060268 / 1e8). "true" So, is the equality test of ScaledDecimal correct ?
see https://0.30000000000000004.com for more about why floating point math does this sometimes
Donald Howard wrote
Hello everyone,
This is an issue I've had awareness of going way back but it's the first time I've had to personally deal with it. I've done some research and found it addressed in a number of ways but given current time pressures and a huge list of to-dos, I thought I'd turn to the community for rapid advice to get me over the hump. The circumstances are summarized below in code and comments suitable for a playground.
"This is the actual arithmetic I want to do... 0.09560268 - 0.005 = 0.09060268"
"Evaluate this in a playground and you'll see this is what floating point arithmetic produces --the first two are wrong, every one after is correct" 0.09560268 - 0.005 "=> 0.09060267999999999". 0.0956026 - 0.005 "=> 0.09060259999999999". 0.095602 - 0.005 "=> 0.090602". 0.09560 - 0.005 "=> 0.0906". 0.0956 - 0.005 "=> 0.0906". 0.095 - 0.005 "=> 0.09".
"This workaround works" 0.09560268 - 0.005 roundTo: 0.00000001 "=> 0.09060268". "but one has to compute number of digits of precision and according to study above, it's not necessary at precisions >= 0.000001"
"What are other suggestions, workarounds or approaches community has?" "THANKS!"
Don Howard
<https://objectguild.com> *Founding Member*
dhoward@
+31653139744 (US) 651-253-7024
-- Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html
Hi Sven, if you dont transform floats, that are not always exactly what they seem to be, you get what you would expect: 0.09560268s8 - 0.005s8 = 0.09060268s8. "true" "of course" a:=0.09560268 asScaledDecimal. 0.09560268s8=a . "false" "you could eg do this:" b:=a roundTo: 0.00000001s8. "then" 0.09560268s8=b . "true" but if you do something like this generally in Float>>asScaledDecimal you could loose some precision that could be unwanted in some other circumstances (or perhaps not). werner On 1/13/20 2:13 PM, Sven Van Caekenberghe wrote:
0.09560268 asScaledDecimal - 0.005 asScaledDecimal = 0.09060268s8. "false"
Ah, yes, yes, sending #asScaledDecimal to a Float is too late, the precision is already lost. It makes total sense now. Thank you, Werner, for the explanation.
On 13 Jan 2020, at 16:13, werner kassens <wkassens@libello.com> wrote:
Hi Sven,
if you dont transform floats, that are not always exactly what they seem to be, you get what you would expect: 0.09560268s8 - 0.005s8 = 0.09060268s8. "true" "of course" a:=0.09560268 asScaledDecimal. 0.09560268s8=a . "false" "you could eg do this:" b:=a roundTo: 0.00000001s8. "then" 0.09560268s8=b . "true"
but if you do something like this generally in Float>>asScaledDecimal you could loose some precision that could be unwanted in some other circumstances (or perhaps not).
werner
On 1/13/20 2:13 PM, Sven Van Caekenberghe wrote:
0.09560268 asScaledDecimal - 0.005 asScaledDecimal = 0.09060268s8. "false"
On 12/01/2020 21:13, Donald Howard wrote:
"Evaluate this in a playground and you'll see this is what  floating point arithmetic produces --the first two are wrong, every one after is correct" 0.09560268 - 0.005 "=> 0.09060267999999999". 0.0956026 - 0.005  "=> 0.09060259999999999". 0.095602 - 0.005  "=> 0.090602".
Wrong in what sense? I am rather sure that the computation is done correctly, meaning that it follows the rules defined by IEEE standard 754. I am also relatively sure (meaning a bit less) that the conversion of the binary result to a decimal output string is correct, in the sense that it applies today's preferred practice of ensuring round-trip equality. So you probably mean that the result is no what you expected. The main point to be clear about is if you care about the binary value or about its decimal representation as a string. If you need the internal value to be exact, you have to switch to something other than binary floats - scaled decimals might work for you. If you only want nice-looking outputs, you can probably get what you want using roundTo: applied to the result. Cheers, Konrad.
You say that the first two results are wrong. No. The first two results are *exactly* what they are supposed to be. Floating point arithmetic is NOT mathematical real arithmetic. The floating point *numbers* are exact rational numbers of the form n * 2^k where n is a (bounded) integer and k is a (bounded) integer. If you enter a number that is not of this form (and within bounds) you will get a *different* number that *is* of that form and is close. The floating point *operations* in IEEE arithmetic are exact when and only when the result is a number of that form (and within bounds), otherwise the result is *approximate*. If you want exact arithmetic on numbers of the form n * 10^k, ANSI Smalltalk provides the ScaledDecimal class, which, sigh, Squeak and Pharo interpret as "rational number *printed* in decimal form but not *computed* using decimal arithmetic", so that can give extremely confusing results too. So what you are going to have to do is use rational numbers, which are in Smalltalk the union of Integer and Fraction. On Mon, 13 Jan 2020 at 09:13, Donald Howard <dhoward@objectguild.com> wrote:
Hello everyone,
This is an issue I've had awareness of going way back but it's the first time I've had to personally deal with it. I've done some research and found it addressed in a number of ways but given current time pressures and a huge list of to-dos, I thought I'd turn to the community for rapid advice to get me over the hump. The circumstances are summarized below in code and comments suitable for a playground.
"This is the actual arithmetic I want to do... 0.09560268 - 0.005 = 0.09060268"
"Evaluate this in a playground and you'll see this is what floating point arithmetic produces --the first two are wrong, every one after is correct" 0.09560268 - 0.005 "=> 0.09060267999999999". 0.0956026 - 0.005 "=> 0.09060259999999999". 0.095602 - 0.005 "=> 0.090602". 0.09560 - 0.005 "=> 0.0906". 0.0956 - 0.005 "=> 0.0906". 0.095 - 0.005 "=> 0.09".
"This workaround works" 0.09560268 - 0.005 roundTo: 0.00000001 "=> 0.09060268". "but one has to compute number of digits of precision and according to study above, it's not necessary at precisions >= 0.000001"
"What are other suggestions, workarounds or approaches community has?" "THANKS!"
Don Howard
<https://objectguild.com> *Founding Member* dhoward@objectguild.com +31653139744 (US) 651-253-7024
On Mon, 13 Jan 2020 at 19:42, Richard O'Keefe <raoknz@gmail.com> wrote:
You say that the first two results are wrong. No. The first two results are *exactly* what they are supposed to be. Floating point arithmetic is NOT mathematical real arithmetic. The floating point *numbers* are exact rational numbers of the form n * 2^k where n is a (bounded) integer and k is a (bounded) integer. If you enter a number that is not of this form (and within bounds) you will get a *different* number that *is* of that form and is close. The floating point *operations* in IEEE arithmetic are exact when and only when the result is a number of that form (and within bounds), otherwise the result is *approximate*.
If you want exact arithmetic on numbers of the form n * 10^k, ANSI Smalltalk provides the ScaledDecimal class, which, sigh,
How could this be improved?
Squeak and Pharo interpret as "rational number *printed* in decimal form but not *computed* using decimal arithmetic"
I'm interested to understand what is the benefit of doing it this way. Anyone know history of it? cheers -ben , so
that can give extremely confusing results too.
So what you are going to have to do is use rational numbers, which are in Smalltalk the union of Integer and Fraction.
On Mon, 13 Jan 2020 at 09:13, Donald Howard <dhoward@objectguild.com> wrote:
Hello everyone,
This is an issue I've had awareness of going way back but it's the first time I've had to personally deal with it. I've done some research and found it addressed in a number of ways but given current time pressures and a huge list of to-dos, I thought I'd turn to the community for rapid advice to get me over the hump. The circumstances are summarized below in code and comments suitable for a playground.
"This is the actual arithmetic I want to do... 0.09560268 - 0.005 = 0.09060268"
"Evaluate this in a playground and you'll see this is what floating point arithmetic produces --the first two are wrong, every one after is correct" 0.09560268 - 0.005 "=> 0.09060267999999999". 0.0956026 - 0.005 "=> 0.09060259999999999". 0.095602 - 0.005 "=> 0.090602". 0.09560 - 0.005 "=> 0.0906". 0.0956 - 0.005 "=> 0.0906". 0.095 - 0.005 "=> 0.09".
"This workaround works" 0.09560268 - 0.005 roundTo: 0.00000001 "=> 0.09060268". "but one has to compute number of digits of precision and according to study above, it's not necessary at precisions >= 0.000001"
"What are other suggestions, workarounds or approaches community has?" "THANKS!"
Don Howard
<https://objectguild.com> *Founding Member* dhoward@objectguild.com +31653139744 (US) 651-253-7024
On Tue, Jan 14, 2020 at 12:41:51AM +1300, Richard O'Keefe wrote:
Squeak and Pharo interpret as "rational number *printed* in decimal form but not *computed* using decimal arithmetic", so that can give extremely confusing results too.
Can you expand on this please? For money-related calculations I have been using Hernán Morales Durand's FixedDecimal: https://github.com/hernanmd/FixedDecimal. Pierce
On Sun, Jan 12, 2020 at 02:13:00PM -0600, Donald Howard wrote:
"What are other suggestions, workarounds or approaches community has?"
This is a good read on the subject: https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html Title is "What every computer scientist should know about floating point arithmetic". Pierce
HI, I would upgrade that "a good read" to a critical read if you do anything with floating point. Â Floating point numbers are not real numbers but rather a small subset, and, have all kinds of funny properties. But we use them just like real numbers and that's what catches us out. cheers bruce
On Sun, Jan 12, 2020 at 02:13:00PM -0600, Donald Howard wrote:
"What are other suggestions, workarounds or approaches community has?"
This is a good read on the subject:
https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
Title is "What every computer scientist should know about floating point arithmetic".
Pierce
Thanks, everyone, for the great input. I will continue to work thru the background readings and recommendations you graciously supplied and go from there. Best regards, - Don On Tue, 14 Jan 2020 at 07:04, Bruce O'Neel <bruce.oneel@pckswarms.ch> wrote:
HI,
I would upgrade that "a good read" to a critical read if you do anything with floating point. Floating point numbers are not real numbers but rather a small subset, and, have all kinds of funny properties. But we use them just like real numbers and that's what catches us out.
cheers
bruce
*14 January 2020 03:05 Pierce Ng <pierce@samadhiweb.com <pierce@samadhiweb.com>> wrote:*
On Sun, Jan 12, 2020 at 02:13:00PM -0600, Donald Howard wrote:
"What are other suggestions, workarounds or approaches community has?"
This is a good read on the subject:
https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
Title is "What every computer scientist should know about floating point arithmetic".
Pierce
participants (9)
-
Ben Coman -
Bruce O'Neel -
Donald Howard -
Konrad Hinsen -
Paul DeBruicker -
Pierce Ng -
Richard O'Keefe -
Sven Van Caekenberghe -
werner kassens