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