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