Whether 6.7 - 2.2 gives 4.5 or something else is a subtle issue,
starting with the fact
that 6.7 and 2.2 cannot be represented precisely in floating-point
format.  In this particular case, the errors happen to match up.
What you *can* rely on in Smalltalk is that (67/10) - (22/10) = (9/2).

Let's just consider h * s / 113 + (r - p).
If h, s, r, and p are all exact numbers (Integers or Fractions) the
result will be an exact number.
So what kinds of number are h, s, r, and p, and *why* are they
like that?  If you are reading them from a file, consider that
Fraction readFrom: '6.7' readStream >>> (67/10)

Is there a specification you could show us?  Some test data?


On Tue, 15 Jun 2021 at 14:24, Esteban Maringolo <emaring...@gmail.com> wrote:
>
> On Mon, Jun 14, 2021 at 10:37 PM Richard O'Keefe <rao...@gmail.com> wrote:
>
> > For what it's worth, I expected ScaledDecimal to act like fixed point
> > arithmetic, and implemented it that way in my own Smalltalk library, where
> > two ScaledDecimals *do* print the same if and only if they are numerically
> > exactly the same.
> > What Squeak and Pharo do is exceedingly odd: a ScaledDecimal
> > is an exact rational number (Integer or Fraction) combined with a precision 
> > that
> > is used for printing, not for calculation.
>
> I pointed out before the weird behavior of ScaledDecimals in Pharo,
> two ScaledDecimal that print the same are not equal. Giving some weird
> comparison issues as result.
>
> > There really isn't any principle of least surprise when it comes to 
> > floating-
> > point arithmetic.  It's full of surprises and edge cases.  Excel in 
> > particular
> > is notorious for messing up due to trying to pretend all is well.
> > In this particular case, the exact result is 4.5
>
> Well... for the end user, it produces what they'd expect. So it might
> mess up, but in a spreadsheet 6.7 - 2.2 should give 4.5.
>
> > There are at least three rules for rounding such numbers: rounding out (5),
> > rounding in (4), and rounding in [banker'salgorithm] (4 here, but 5.5 -> 6).
> > So you are pushing up against an edge case for exact hand calculation!
>
> I implemented a Float>>#roundedHandicap method that does something
> like the banking algorithm, but rounds positive numbers towards the
> next integer and negative numbers towards zero.
> E.g.
> 0.49 -> 0
> 0.5 -> 1
> -0.5 -> 0
> -0.51 -> -1
>
> Nothing uses more than one decimal, so a ScaledDecimal would work but
> the specification says that it should use all possible precision in
> intermediate calculations, so I cannot use it.
>
> > I think you need to re-express your entire calculation to use exact 
> > arithmetic.
>
> I really don't know how to do this, any pointers?
>
> Nothing is more straightforward than addition and subtraction to me,
> 6.7 - 2.2 is the simplest it can get.
>
> The common formula here is: h * s / 113 + (r - p), but in this
> particular case s was 113 so it removed the "troubling" part.
>
> > That or get agreement on "de minimis non curat lex".
>
> I had to search for that expression. Now I know, I agree.
>
> Regards,
>
> Esteban A. Maringolo
>
>
>
> >
> >
> > On Tue, 15 Jun 2021 at 08:45, Esteban Maringolo <emaring...@gmail.com> 
> > wrote:
> > >
> > > I'm coming back to this because I've been bitten by these floating
> > > points things again.
> > >
> > > If in Pharo [1] you do:
> > > a := 6.7 + (32.8 - 35)
> > >
> > > It will produce:
> > > 4.499999999999997
> > >
> > > Which, when rounded, will produce 4.
> > >
> > > In other places [2] I do the same simple addition and subtraction it
> > > produces 4.5, that when rounded will produce 5.
> > >
> > > I know now that Pharo doesn't lie to me while other systems do, and
> > > all that Richard pointed to before.
> > >
> > > The issue here is that I'm following some calculation formula that was
> > > defined in some of the "other" systems, and so when I follow such a
> > > formula I get these edgy cases where my system produces a different
> > > output.
> > >
> > > In this case the formula is for golf handicap calculations, and it
> > > caused my system to give 4 instead of 5 to a player, resulting in
> > > giving the first place to a player other than the one deserved.
> > > It was no big deal (it's not The Masters), but these cases appear from
> > > time to time.
> > >
> > > Is there any way to "configure" the floating point calculation to
> > > behave as the "other systems"?
> > >
> > > What is the best way to anticipate these situations, am I the only one
> > > being bitten by these issues?
> > >
> > > Thanks in advance for any hints about these problems.
> > >
> > >
> > > Best regards,
> > >
> > > [1] Dolphin Smalltalk, JS, Python, Ruby, Dart produces the same output as 
> > > Pharo.
> > > [2] VisualWorks, VAST, Excel, VB and all calculators I tried
> > >
> > >
> > >
> > > Esteban A. Maringolo
> > >
> > > On Tue, Sep 8, 2020 at 12:45 AM Esteban Maringolo <emaring...@gmail.com> 
> > > wrote:
> > > >
> > > > On Tue, Sep 8, 2020 at 12:16 AM Richard O'Keefe <rao...@gmail.com> 
> > > > wrote:
> > > > >
> > > > > "7.1 roundTo: 0.1 should return 7.1"
> > > > > You're still not getting it.
> > > >
> > > > I was until Konrad explained it.
> > > >
> > > > > Binary floating point CANNOT represent either of those numbers.
> > > > > You seem to be assuming that Pharo is making some mistake.
> > > > > It isn't.  All it is doing is refusing to lie to you.
> > > > <snip>
> > > > > The systems that print 7.1 are LYING to you,
> > > > > and Pharo is not.
> > > >
> > > > I'm not assuming a mistake from Pharo, I had a wrong expectation what
> > > > to get if I round to that precision.
> > > > I don't know whether other systems lie or simply fulfill user
> > > > expectations, if you send the #roundTo: to a float, I did expect to
> > > > get a number with the same precision.
> > > > That is my expectation as a user. As in the other thread I expected
> > > > two scaled decimals that are printed equal to also be compared as
> > > > equal  (which they don't).
> > > >
> > > > Whether there is a good reason for those behaviors is beyond my
> > > > current comprehension, but it certainly doesn't follow the "principle
> > > > of least surprise".
> > > >
> > > > In any case, the method proposed by Tomohiro solved my issues.
> > > >
> > > > Regards,
> > > >
> > > > Esteban A. Maringolo

Reply via email to