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

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


2016-10-26 9:14 GMT+02:00 stepharo <steph...@free.fr <mailto:steph...@free.fr>>:

    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