Hi guys
I loaded the slice 15471 of werner and I run https://pharo.fogbugz.com/f/cases/15471/Can-t-round-Float-fmax-to-2-decimal-places testIfCompletelyBroken "If the results are not these values (accounting for precision of printing) then something is horribly wrong" gen seed: 2345678901. self assert: (((1 to: 10) collect: [:i | gen next round: 15]) = #(0.149243269650845 0.331633021743797 0.75619644800024 0.393701540023881 0.941783181364547 0.549929193942775 0.659962596213428 0.991354559078512 0.696074432551896 0.922987899707159 )). I get the following. Is it correct? #(0.220388752510952 0.073763451573329 0.74233059293699 0.350275491993071 0.080193927548916 0.819340314631974 0.652668019594936 0.391405332084468 0.349416343657959 0.640487859323848) |
Hi Stephan,
definitely no. after the test is run, the seed has changed, perhaps you did not reset the seed. ill look into this this night, have to work now, ok? werner On 11/04/2016 03:29 PM, stepharo wrote: > Hi guys > > I loaded the slice 15471 of werner and I run > > https://pharo.fogbugz.com/f/cases/15471/Can-t-round-Float-fmax-to-2-decimal-places > > > > testIfCompletelyBroken > > "If the results are not these values (accounting for precision of > printing) > then something is horribly wrong" > > gen seed: 2345678901. > self assert: (((1 to: 10) collect: [:i | gen next round: 15]) = > #(0.149243269650845 0.331633021743797 0.75619644800024 > 0.393701540023881 0.941783181364547 0.549929193942775 > 0.659962596213428 0.991354559078512 0.696074432551896 > 0.922987899707159 )). > > I get the following. Is it correct? > > #(0.220388752510952 0.073763451573329 0.74233059293699 > 0.350275491993071 0.080193927548916 0.819340314631974 > 0.652668019594936 0.391405332084468 0.349416343657959 0.640487859323848) > > |
Le 4/11/16 à 17:03, werner kassens a écrit : > Hi Stephan, > definitely no. after the test is run, the seed has changed, perhaps > you did not reset the seed. I just run the test. Nothing else. > ill look into this this night, have to work now, ok? tx! > werner > > On 11/04/2016 03:29 PM, stepharo wrote: >> Hi guys >> >> I loaded the slice 15471 of werner and I run >> >> https://pharo.fogbugz.com/f/cases/15471/Can-t-round-Float-fmax-to-2-decimal-places >> >> >> >> testIfCompletelyBroken >> >> "If the results are not these values (accounting for precision of >> printing) >> then something is horribly wrong" >> >> gen seed: 2345678901. >> self assert: (((1 to: 10) collect: [:i | gen next round: 15]) = >> #(0.149243269650845 0.331633021743797 0.75619644800024 >> 0.393701540023881 0.941783181364547 0.549929193942775 >> 0.659962596213428 0.991354559078512 0.696074432551896 >> 0.922987899707159 )). >> >> I get the following. Is it correct? >> >> #(0.220388752510952 0.073763451573329 0.74233059293699 >> 0.350275491993071 0.080193927548916 0.819340314631974 >> 0.652668019594936 0.391405332084468 0.349416343657959 0.640487859323848) >> >> > > > |
Hi Stephane,
i uploaded a SLICE-Issue-15471-Cant-round-Float-fmax-to-2-decimal-places-WernerKassens.2 to the inbox with these changes: i corrected RandomTest>>testIfCompletelyBroken, completed tests with some border cases and the usual specifications, and added your comment to Float>>round:. the testIfCompletelyBroken needed to be changed: "original in test: #(0.149243269650845 0.331633021743797 0.75619644800024 0.393701540023881 0.941783181364547 0.549929193942775 0.659962596213428 0.991354559078512 0.696074432551896 0.922987899707159 )" gen := Random seed: 2345678901. raw:= (1 to: 10) collect: [:i | gen next] . "#(0.14924326965084453 0.3316330217437972 0.7561964480002394 0.3937015400238808 0.9417831813645471 0.5499291939427746 0.6599625962134277 0.991354559078512 0.6960744325518955 0.922987899707159)" gen seed: 2345678901. test:=(1 to: 10) collect: [:i | gen next round: 15]. "#(0.149243269650845 0.331633021743797 0.756196448000239 0.393701540023881 0.941783181364547 0.549929193942775 0.659962596213428 0.991354559078512 0.696074432551895 0.922987899707159)" "rounding here is correct, 5 and higher is rounded up, 4 and lower down" "differences to the original are the result of originally wrong rounding; compare with the raw result." werner |
Hi,
i noticed that i have quite some difficulties in producing a slice that makes at least a minimal sort of sense, hence a stupid question: is it ok to make a slice dependent on a preceeding slice? i would guess not, since in the meantime a lot of newer versions of a package in the slice are in Pharo60/main hence there will be regressions that have to be filtered out by the integrator (unfortunately it is relatively unclear to me how the integrator operates and how much is automated). but if it is not ok, how do i proceed if i only want to change a small part of the preceeding slice? werner |
In reply to this post by wernerk
Hi,
fwiw when i redid that #testIfCompletelyBroken i noticed a sort of bug in that new #round: - well, i think its a feature -, but i should probably mention it nevertheless: 1.15 round:1. "1.1" "down" 1.25 round:1. "1.3" "up" 1.35 round:1. "1.4" "up" 1.45 round:1. "1.4" "down" 1.55 round:1. "1.6" "up" 1.65 round:1. "1.6" "down" btw the same happens with #printShowingDecimalPlaces: (which is unchanged, happens eg also in 4.0). if one wants to change this to the normal behaviour, i'd guess one could do it perhaps by using #asMinimalDecimalFraction instead of #asFraction in #round: i have to admit that i have no problems at all with this idiosyncrasy and would _not use #asMinimalDecimalFraction in #round: for these reasons: 1. i see it as a poor mans round-to-even (this bankers rounding is done so that the sum of rounded numbers does not have an upward bias in relation to the sum of the original unrounded numbers). 2. although i havent tested it, i assume #asMinimalDecimalFraction is noticeably slower than #asFraction, because the former one has to use a #whileFalse: iteration. 3. round-to-even imprints a definite structure on eg random-numbers, the structure of the new #round: is at least less simple & does not produce too many even decimals, insofar it's even a rich mans round-to-even (in a way a non-random, hence repeatable, stochastic rounding). normal rounding of course introduces an even less wanted upward bias. But <stupid grin> perhaps somebody else wants to have a more predictable behaviour of #round:? werner On 11/04/2016 10:26 PM, werner kassens wrote: > Hi Stephane, > i uploaded a > SLICE-Issue-15471-Cant-round-Float-fmax-to-2-decimal-places-WernerKassens.2 > to the inbox with these changes: > i corrected RandomTest>>testIfCompletelyBroken, completed tests with > some border cases and the usual specifications, and added your comment > to Float>>round:. |
On 11/05/2016 06:17 AM, werner kassens wrote:
> Hi, > fwiw when i redid that #testIfCompletelyBroken i noticed a sort of bug > in that new #round: - well, i think its a feature -, but i should > probably mention it nevertheless: > 1.15 round:1. "1.1" "down" > 1.25 round:1. "1.3" "up" > 1.35 round:1. "1.4" "up" > 1.45 round:1. "1.4" "down" > 1.55 round:1. "1.6" "up" > 1.65 round:1. "1.6" "down" > btw the same happens with #printShowingDecimalPlaces: (which is > unchanged, happens eg also in 4.0). > > if one wants to change this to the normal behaviour, i'd guess one > could do it perhaps by using #asMinimalDecimalFraction instead of > #asFraction in #round: This is, in part, an example of it being difficult to predict, at a glance, what #round: should do, without an understanding of the strengths and limitations of binary floating point numbers. Remember that Floats are not usually exact representations of nice decimal fractions. So most of these numbers are not *exactly* halfway between their possible roundings. 1.15 < (115/100) "true" 1.25 = (125/100) "true" 1.35 > (135/100) "true" 1.45 < (145/100) "true" 1.55 > (155/100) "true" 1.65 < (165/100) "true" In every case except 1.25, the answer is the correct rounding, that, is the one that is closer. For 1.25, the number *is* exactly halfway between two roundings. For round-to-even (which I recommend) the answer should be 1.2, so it gets that one "wrong". Regards, -Martin |
Hi Martin,
yes, what i said was wrong (!). i got irritated when i used #printShowingDecimalPlaces: on a directly entered decimal number <g> and got a seemingly upwards rounded number. of course that result was also correct. iow there is no problem in the new #round: or #printShowingDecimalPlaces:. sorry for my confusion. werner On 11/06/2016 01:57 AM, Martin McClure wrote: > On 11/05/2016 06:17 AM, werner kassens wrote: >> Hi, >> fwiw when i redid that #testIfCompletelyBroken i noticed a sort of >> bug in that new #round: - well, i think its a feature -, but i should >> probably mention it nevertheless: >> 1.15 round:1. "1.1" "down" >> 1.25 round:1. "1.3" "up" >> 1.35 round:1. "1.4" "up" >> 1.45 round:1. "1.4" "down" >> 1.55 round:1. "1.6" "up" >> 1.65 round:1. "1.6" "down" >> btw the same happens with #printShowingDecimalPlaces: (which is >> unchanged, happens eg also in 4.0). >> >> if one wants to change this to the normal behaviour, i'd guess one >> could do it perhaps by using #asMinimalDecimalFraction instead of >> #asFraction in #round: > > > This is, in part, an example of it being difficult to predict, at a > glance, what #round: should do, without an understanding of the > strengths and limitations of binary floating point numbers. > > Remember that Floats are not usually exact representations of nice > decimal fractions. So most of these numbers are not *exactly* halfway > between their possible roundings. > > 1.15 < (115/100) "true" > 1.25 = (125/100) "true" > 1.35 > (135/100) "true" > 1.45 < (145/100) "true" > 1.55 > (155/100) "true" > 1.65 < (165/100) "true" > > In every case except 1.25, the answer is the correct rounding, that, > is the one that is closer. For 1.25, the number *is* exactly halfway > between two roundings. For round-to-even (which I recommend) the > answer should be 1.2, so it gets that one "wrong". > > Regards, > > -Martin > > > |
In reply to this post by Martin McClure-2
Hey Martin... I agree on the confusion.
> I still recommend not rounding the number itself, but rounding the printing of the number Yes. If "rounding" had well specified behavior that was at least somewhat reasonable (e.g. return the closest floating point value and round to even if tied), I'd accept floating point results that don't print "pretty" in base 10. That's the way things are, there's no point in pretending IEEE-754 is not base 2. If "rounding" is being done in place of "printing", or obtaining a "string representation", I think that won't work as expected because 0.1 not representable etc. For "printing", the algorithms were Dragon4 and Grisu3 last time I checked. For "floating point that works nice in base 10", there's IEEE-854. For those unfamiliar with the spec, it's been implemented in non-exotic hardware already. > you did proof that, as you said "1.2000000000000002 *is* the correct answer for 1.19 roundTo: 0.1.". As a suggestion for these types of problems, try iterating over a floating point bit range converting each to a true fraction and see which one is closest? > testIfCompletelyBroken [doesn't round to even] I'd agree rounding to even would be better. Guillermo, > And also: I'd argue that you NEVER EVER want to use simple Floats for financial applications Define "financial" applications? In the risk management world, tying down that last $1 difference will likely cost more electricity (and way more time) than the $1 is worth. John, > While ANSI says that the numbers should be converted using the default conversion table, all of the Smalltalk’s that I’ve tried don’t follow that. I’ve tried Dolphin, VW, Pharo, & VAST, and all return fractions. I prefer this behavior over the ANSI behavior. I agree that ANSI doesn't always make the best sense. If it were up to me, I'd follow the relevant standard to the letter. That's more important than providing a custom interpretation of an interoperability mechanism just for Smalltalk (or a particular dialect) by default. Nicolas, > printShowingDecimalPlaces: That's quite a long selector. Has anyone considered an approach along the lines of this? 1.2345 %f #'3.2' => ' 1.23' 1.2345 %f #'03.2' => '001.23' A reminder: calling printf() via FFI is undefined behavior. Andres. On 10/26/16 23:31 , Martin McClure wrote: > On 10/26/2016 08:27 AM, stepharo wrote: >> So what is the definition of printShowingMaxDecimalDigit:? >> I have the impression that there is a confusion between the rounding a >> number and the printing of his value in a given format. > > Yes, I see quite a bit of confusion in this thread about that. > >> we can deprecate roundTo: if necessary. > > I think roundTo: is OK. #round: is not, and should be deprecated (at > least for Floats). For Floats, the idea of rounding to a specific number > of decimal digits is a fantasy. Here's why: Floats cannot exactly > represent most common decimal fractions. For example: > > 0.1 -- not representable > > 0.2 -- not representable > > 0.3 -- not representable > > 0.4 -- not representable > > 0.5 -- hey, representable! > > 0.6 -- not representable > > 0.7 -- not representable > > 0.8 -- not representable > > 0.9 -- not representable > > 1.0 -- representable. > > *Printing* a Float to a specific rounded decimal format is a sensible > idea, and should be encouraged. But trying for a "rounded Float" > *number* just can't be done exactly (except by converting to a Fraction). > > Fractions can be rounded to exact decimal fractions, so something like > "myFraction roundTo: 1/100" makes sense. But the current implementation > of round: on Fraction that converts to a Float just gets you the misery > detailed above. > > > On 10/26/2016 01:00 PM, Nicolas Cellier wrote: >> 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) > > The double rounding problem is not the fundamental problem, the > fundamental problem is that what is desired does not exist, because > Floats cannot exactly represent most decimal fractions. So this can't > really fix it. > >> >> For Fraction (15472), choose an exact representation for result rather >> than Float. This is because such method is particularly usefull for >> financial/monetary applications. >> > Yes. Fraction or ScaledDecimal. Not Floats, unless the developer > understands the needs of the financial world and the limitations of > Floats very well. > > > Regards, > > -Martin > |
On 11/25/2016 08:33 PM, Andres Valloud wrote:
> If "rounding" had well specified behavior that was at least somewhat > reasonable (e.g. return the closest floating point value and round to > even if tied), I'd accept floating point results that don't print > "pretty" in base 10. That's the way things are, there's no point in > pretending IEEE-754 is not base 2. > > If "rounding" is being done in place of "printing", or obtaining a > "string representation", I think that won't work as expected because > 0.1 not representable etc. > > For "printing", the algorithms were Dragon4 and Grisu3 last time I > checked. Thanks for the reference! Grisu3 looks interesting. > > For "floating point that works nice in base 10", there's IEEE-854. > For those unfamiliar with the spec, it's been implemented in > non-exotic hardware already. > Base 2 and base 10 are now both covered in IEEE-754 as of the 2008 revision (which also ties up some loose ends that were not specified adequately in IEEE 754-1985) Regards, -Martin |
Free forum by Nabble | Edit this page |