Thanks ***A LOT*** nicolas.


I've put a single slice in the inbox for the 3 issues because they all are related.
See slice comment:

For Float, implement guard to prevent overflow (15471), and use exact representation for intermediate results (asFraction) so as to avoid double rounding problems (15473)

For Fraction (15472), choose an exact representation for result rather than Float. This is because such method is particularly usefull for financial/monetary applications.

2016-10-26 17:28 GMT+02:00 stepharo <[email protected] <mailto:[email protected]>>:



    Le 26/10/16 à 14:52, Nicolas Cellier a écrit :
    Sorry for being slow minded,
    yes of course financial apps is exactly the case where round:
    would be usefull and NEEDS to be exact.

    so what is the solution?
    I'm lost again.

        Hi Nicolas,
        yes, i know. suppose you calc some financial thing and one
        intermediate result will be in $. you have to round this
        Fraction-result  to 2 decimals. now you use this to further
        calc basepoints as the final result. you have to convert this
        to 3 decimals. looking at this final result with 2 decimals
        can be be irritating for a moment, if you debug the calcs.
        and <g> btw i never use scaledDecimals.
        werner


        On 10/26/2016 02:06 PM, Nicolas Cellier wrote:


        2016-10-26 13:11 GMT+02:00 test <[email protected]
        <mailto:[email protected]>>:

            Hi Nicolas,
            regarding rounding Fractions:
            i use fractions if i want to get an exact result (eg for
            comparing the result with Float calculations). if
            #round: returns a Float all further calcs (with
            Fractions) will get contaminated, since the rest will
            become Floats too. Hence the "asScaledDecimal:
            numberOfWishedDecimal" seems better to me, but i wonder
            why these transformations at the end are necessary at
            all? just for the looks? i'd suppose every person, who
            knows how to use Fractions, also knows how to append a
            #asScaledDecimal: to a result by himself, should he want
            that.

            taking as an example financial calcs that first use 2
            decimals. occasionaly the final result will be
            basepoints, often small ones like 0.003. with
            scaledDecimals the result would be (ok, look like) 0
            since scaledDecimals also contaminate the calc. of
            course one could correct this simply with an
            #asScaledDecimal:3 at the end. nevertheless a first look
            at the zero result would surprise me for a tenth of a
            second.
            werner


        Hi Werner,
        I don't know the purpose of round: at all.
        Most often this kind of message was used before printing
        probably because lack of versatile formatted print messages.
        In Squeak I replaced most usages of roundTo: by
        printShowing(Max)DecimalPlaces:.
        Now if it has been added in Pharo and other languages, there
        must be some use cases I presume.
        Maybe the analysis could be carried on these use cases?

        Beware, converting a Fraction asScaledDecimal will NOT round.
        Only the printString is rounded, but the number keeps its
        whole precision.
        Example (1/3 asScaledDecimal: 1)*3 = 1.0s, not 0.9s.

        ScaledDecimals as they are now are just Fraction with a
        different printString...
        Not very much added value.

        Nicolas

            On 10/26/2016 09:58 AM, Nicolas Cellier wrote:


            2016-10-26 9:14 GMT+02:00 stepharo <[email protected]
            <mailto:[email protected]>>:

                Hi nicolas

                So what is the solution? We can integrate fast a
                solution.
                I would really like to see them fix in Pharo 60.
                I'm writing a book for newbie and this is the third
                time I change one chapter
                so may be I should stop and throw away this chapter.


            1) for Fraction:

            round: numberOfWishedDecimal
                v := 10 raisedTo: numberOfWishedDecimal.
                ^ ((self * v) rounded / v) asFloat

            or just replace asFloat if you wish to remain exact:

            round: numberOfWishedDecimal
                v := 10 raisedTo: numberOfWishedDecimal.
                ^ ((self * v) rounded / v) asScaledDecimal:
            numberOfWishedDecimal

            2) for Float, it is in 15471:

            round: numberOfWishedDecimal
                | v maxNumberOfDecimals |
                maxNumberOfDecimals := self class precision - 1 -
            (self exponent max: self class emin).
                maxNumberOfDecimals < numberOfWishedDecimal ifTrue:
            [^self].
                v := 10 raisedTo: numberOfWishedDecimal.
                ^ ((self asFraction * v) rounded / v) asFloat

            or if Fraction already answers a Float:

            round: numberOfWishedDecimal
                | maxNumberOfDecimals |
                maxNumberOfDecimals := self class precision - 1 -
            (self exponent max: self class emin).
                maxNumberOfDecimals < numberOfWishedDecimal ifTrue:
            [^self].
                ^ self asFraction round: numberOfWishedDecimal

            It's slower than current implementation, but will round
            exactly to the nearest Float.
            It's possible to have faster implementation up to 22
            decimals if you provide a fused-multiply-accumulate
            primitive...







Reply via email to