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]>:

>
>
> 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]>:
>>
>>> 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]>:
>>>
>>>> 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