Hello.
I know there are many similar questions. Maybe somebody give me fast answer. 146.015 roundTo: 0.01 => 146.01 I guess internal representation of 146.015 is something like 146.014999999999... That's why rounding result is 146.01 But how I can round arbitrary float my math root? How to fix my example to get 146.02? Best regards, Denis |
Hi Denis,
If you decompose the operation performed by round: (146.015 / 0.01) rounded * 0.01 '146.015' asFloat is inexact '0.01' asFloat is inexact / 0.01 operation is inexact '0.01' asFloat is inexact (again) * 0.01 operation is inexact That means cumulating 5 inexact operations, how do you say "jouer à la roulette russe"? Pharo guys did propose a better scheme (146.015 * 100.0) rounded / 100.0 Since '100.0' asFloat is exact, that leave only 2 inexact operations and works much better (and we know the last one rounds exactly). But if (146.015 asFraction < 146.015s3) then you still have a problem with inexactness of original value. I see two solutions for this root problem: - don't use Float, but Fraction or ScaledDecimals - use a trick, asMinimalDecimalFraction which I proposed in http://code.google.com/p/pharo/issues/detail?id=4957 that will convert ('146.015' asFloat) to the exact fraction that is printed 146015/1000... (x asMinimalDecimalFraction roundTo: 1/100) asFloat would thus be close to your requirements... Nicolas 2012/9/7 Denis Kudriashov <[hidden email]>: > Hello. > > I know there are many similar questions. > > Maybe somebody give me fast answer. > > 146.015 roundTo: 0.01 => 146.01 > > I guess internal representation of 146.015 is something like > 146.014999999999... > That's why rounding result is 146.01 > > But how I can round arbitrary float my math root? > How to fix my example to get 146.02? > > Best regards, > Denis |
Thank's for your answer. Only one of your solutions works: (146.015 asMinimalDecimalFraction roundTo: 1/100) asFloat => 146.02 Others not works: (146.015 * 100.0) rounded / 100.0 => 146.01 (146.015 asFraction roundTo: 1/100) asFloat => 146.01 2012/9/7 Nicolas Cellier <[hidden email]> Hi Denis, |
On Fri, Sep 7, 2012 at 7:41 AM, Denis Kudriashov <[hidden email]> wrote:
> Thank's for your answer. > Only one of your solutions works: > (146.015 asMinimalDecimalFraction roundTo: 1/100) asFloat => 146.02 > > Others not works: > > (146.015 * 100.0) rounded / 100.0 => 146.01 > (146.015 asFraction roundTo: 1/100) asFloat => 146.01 > Another option it to load FixedDecimal, and use it for you fixed place work: ('146.015' asFixedDecimal: 3) roundTo: ('0.01' asFixedDecimal: 2) ==> 146.02 (Yes, Nicolas, I still haven't come up with a short way of specifying FixedDecimals, but it will still load into Pharo without an issue.) http://www.squeaksource.com/FixedDecimal.html -Chris |
In reply to this post by Denis Kudriashov
2012/9/7 Denis Kudriashov <[hidden email]>:
> Thank's for your answer. > Only one of your solutions works: > (146.015 asMinimalDecimalFraction roundTo: 1/100) asFloat => 146.02 > > Others not works: > > (146.015 * 100.0) rounded / 100.0 => 146.01 > (146.015 asFraction roundTo: 1/100) asFloat => 146.01 > > That's expected, '146.015' asFloat is already smaller than (146015/1000) so if you convert the float value asFraction or asScaledDecimal, it's too late, rounding error is already there. You have to use Fraction, ScaledDecimal or FixedDecimal of Chris right from the beginning, and don't use Float at all. > 2012/9/7 Nicolas Cellier <[hidden email]> >> >> Hi Denis, >> If you decompose the operation performed by round: >> >> (146.015 / 0.01) rounded * 0.01 >> >> '146.015' asFloat is inexact >> '0.01' asFloat is inexact >> / 0.01 operation is inexact >> '0.01' asFloat is inexact (again) >> * 0.01 operation is inexact >> >> That means cumulating 5 inexact operations, how do you say "jouer à la >> roulette russe"? >> >> Pharo guys did propose a better scheme >> >> (146.015 * 100.0) rounded / 100.0 >> >> Since '100.0' asFloat is exact, that leave only 2 inexact operations >> and works much better (and we know the last one rounds exactly). >> >> But if (146.015 asFraction < 146.015s3) then you still have a problem >> with inexactness of original value. >> >> I see two solutions for this root problem: >> - don't use Float, but Fraction or ScaledDecimals >> - use a trick, asMinimalDecimalFraction which I proposed in >> http://code.google.com/p/pharo/issues/detail?id=4957 that will convert >> ('146.015' asFloat) to the exact fraction that is printed >> 146015/1000... >> >> (x asMinimalDecimalFraction roundTo: 1/100) asFloat would thus be >> close to your requirements... >> >> Nicolas >> >> 2012/9/7 Denis Kudriashov <[hidden email]>: >> > Hello. >> > >> > I know there are many similar questions. >> > >> > Maybe somebody give me fast answer. >> > >> > 146.015 roundTo: 0.01 => 146.01 >> > >> > I guess internal representation of 146.015 is something like >> > 146.014999999999... >> > That's why rounding result is 146.01 >> > >> > But how I can round arbitrary float my math root? >> > How to fix my example to get 146.02? >> > >> > Best regards, >> > Denis >> > |
On Fri, Sep 7, 2012 at 10:34 AM, Nicolas Cellier
<[hidden email]> wrote: > 2012/9/7 Denis Kudriashov <[hidden email]>: >> Thank's for your answer. >> Only one of your solutions works: >> (146.015 asMinimalDecimalFraction roundTo: 1/100) asFloat => 146.02 >> >> Others not works: >> >> (146.015 * 100.0) rounded / 100.0 => 146.01 >> (146.015 asFraction roundTo: 1/100) asFloat => 146.01 >> >> > > That's expected, '146.015' asFloat is already smaller than > (146015/1000) so if you convert the float value asFraction or > asScaledDecimal, it's too late, rounding error is already there. You > have to use Fraction, ScaledDecimal or FixedDecimal of Chris right > from the beginning, and don't use Float at all. > If you used ScaledDecimal, you will need to make sure that all parts of it are ScaledDecimal, too - no mixing of Floats anywhere: This doesn't work: 146.015s3 roundTo: 0.01 => 146.01 but this does 146.015s3 roundTo: 0.01s2 => 146.02s2 -Chris |
Free forum by Nabble | Edit this page |