Hi werner to load a slice: - select it and press load. to create a slice - + slice - then select the package that will compose the slice - save the slice in the inbox Can you retry and let me know what did not work?
Stef Le 29/10/16 à 17:01, test a écrit :
|
In reply to this post by wernerk
Le 29/10/16 à 17:01, test a écrit :
This is an experience that we should remove "< expr: '(1/3 round: 2)' result: (33/100) >" -> "(1/3 round: 2)' -> (33/100)"
|
In reply to this post by Martin McClure-2
I'm favor to deprecate round: too. Thanks you all for your analysis. I will reread the thread
carefully to learn.
Stef Le 27/10/16 à 18:12, Martin McClure a
écrit :
|
In reply to this post by Ben Coman
Hi Ben,
this explanation helped me most, because i <big grin> realized that i need an account with a password, which i dont have. so things have resolved themselves. thanks werner |
In reply to this post by stepharo
On 10/30/2016 09:45 AM, stepharo wrote:
> > I'm favor to deprecate round: too. > > Thanks you all for your analysis. I will reread the thread carefully > to learn. > Hi Stephane, just to sum up my arguments: 1. Floats & Fractions represent almost the same thing, hence they should have the same API! iow if Float>>round: is deprecated it should imo also be deprecated in Fractions. and i dont see what is gained by generally deprecating every #round: (eg i like to use it). if it is because you want to have a small image, i'd guess, one could put ScaledDecimal in its own package (as long as there are no dependencies of numbers on it introduced) and have an image without that. the memory gain would be bigger & imo the usability loss smaller. 2. most decimals are not representable as Floats. Ok, so what? pi is not representable too, you dont deprecate Float>>pi because of that, right? werner |
In reply to this post by wernerk
or perhaps it worked now, i think i uploaded
SLICE-Issue-15471-Cant-round-Float-fmax-to-2-decimal-places-WernerKassens.1 <http://www.smalltalkhub.com/#%21/%7EPharo/Pharo60Inbox/versions/SLICE-Issue-15471-Cant-round-Float-fmax-to-2-decimal-places-WernerKassens.1> werner |
In reply to this post by wernerk
Hi,
just a simple numerical example using nicolas' implementation: 1.199999999999999999 round: 1. "1.2" i'd guess this result is more or less what a beginner would expect with this line. how would he do it with roundTo:? perhaps this way? 1.199999999999999999 roundTo: 0.1. "1.2000000000000002" i'm not so sure that he would immediately see that he'd need to do it this way: (1.199999999999999999 roundTo: (1/10))asFloat. "1.2" werner |
oops, make that original number 1.19 in the example.
werner |
tl;dr:
1.2000000000000002 *is* the correct answer for 1.19 roundTo: 0.1. (1.19 roundTo: (1/10))asFloat gives a different answer because it's rounding to a multiple of exactly 0.1, not the Float nearest to 0.1. On 10/31/2016 08:35 AM, test wrote: > oops, make that original number 1.19 in the example. OK, so the examples are now 1.19 round: 1. 1.19 roundTo: 0.1. (1.19 roundTo: (1/10))asFloat I should note that the final example *should* result in a Float without having to have #asFloat sent to it. Per ANSI and traditional Smalltalk practice, any operation where the receiver *or* the argument is a Float produces a Float. Since 0.1 is not quite equal to 1/10, the correct answer may not be the same for the latter two examples. Whether you define #round: to be one or the other is an interesting question. I've learned the hard way not to trust the results from Smalltalk math libraries too far, so let's manually figure out what the correct answer is for each of these, and see if Pharo's doing it right. To start, every Float (ignoring infinities, NaNs, and subnormals) is (by definition) a Fraction constrained to have a numerator in the range [2**52..2**53) and a denominator that is a power of two. Pharo says: 0.1 asFraction ==> (3602879701896397/36028797018963968) Is this correct? The numerator is less than 2**52, so this Fraction has been reduced. Let's restore it to what it would be in its Float form by multiplying numerator and denominator by, in this case, 2: 7205759403792794 ----------------- 72057594037927936 It's easy to see that this fraction is very nearly equal to 1/10, and to see that there could be no Float closer to 1/10. --- But I haven't shown the conversion from the string '0.1' to the actual Float instance is correct. It's possible that there's some rounding error there, which is reversed by a rounding in a different direction by the #asFraction. The Float for '0.1' is two words with values, 1069128089 and 2576980378. Convert to hex and combine them, you get 16r3FB999999999999A The numerator of our fraction is the low-order 52 bits of this, with a 1 added on the most-significant end, so 16r1999999999999A, which in decimal is 7205759403792794. Which is what we got above, so we're good so far. ======== Doing the same analysis on 1.19 gives a numerator of 16r130A3D70A3D70A, and a denominator 1/16th the previous one, or 5359283556570890 ---------------- 4503599627370496 This one's harder, I can't just look at it and say it's the closest possible to 1.19. But we know that 1.19 = 119/100. 119/100 * 4503599627370496/4503599627370496 = 535928355657089024 ------------------ 450359962737049600 and is still exactly 1.19. But to make a representable Float we have to divide numerator and denominator by 100, rounding the numerator if necessary. And we can see that the numerator is correctly rounded, so Pharo also converts the string '1.19' into a Float correctly. How does Pharo do on 1.19 asFraction? (2679641778285445/2251799813685248) Once again, this has been reduced by dividing numerator and denominator by two, but it's numerically correct. ====== Now that we know that we have the correct Fractions for the floats, we can check the rounding functions. 1.19 roundTo: 0.1 should ideally be equivalent to (1.19 asFraction roundTo: 0.1 asFraction) asFloat. In Pharo 5, 1.19 asFraction roundTo: 0.1 asFraction ==> (10808639105689191/9007199254740992) For this to correct, (10808639105689191/9007199254740992) must be a multiple of (3602879701896397/36028797018963968), since that's 0.1 asFraction. Is it a multiple? We can align the denominators by multiplying (10808639105689191/9007199254740992) by 4/4, and we get 43234556422756764 ----------------- 36028797018963968 which would be a multiple of 3602879701896397 ----------------- 36028797018963968 iff 43234556422756764 is a multiple of 3602879701896397. Looking at the original problem (1.19 roundTo: 0.1) we'd expect the multiple to be 12. Sure enough, 3602879701896397 * 12 ==> 43234556422756764. So we're correct so far. Now we have to convert our answer to the nearest representable Float. Our denominator is already a power of two, but our numerator is out of range -- it's too large. It's even, so we can cut it in half, getting 21617278211378382 Still too large, still even. Cut it in half again: 10808639105689191 Just a bit too large. Cut it in half again: 5404319552844595.5 Now it's in range [2**52..2**53) but it's not an integer, so we must round. Our number is exactly halfway between two representable numbers, so by IEEE754 we round to the even one, which is 5404319552844596 The Float we get back from 1.19 roundTo: 0.1 is 16r3FF3333333333334 and the numerator part of that is 16r13333333333334, or 5404319552844596 Which agrees with what we computed before. So this *is* the correct Float result. And it prints as 1.2000000000000002. This print string implies that there is a Float nearer to 1.2 than this. 1.2 is represented as 16r3FF3333333333333, so one representable Float less than the result of the #roundTo:. But, as we've shown, 1.2000000000000002 is *correct*. (Which was not what I expected when started this -- I suspected there might be rounding error in the computation of #roundTo:. But for this example, there isn't). I haven't done the full analysis of it, but I expect that (1.19 roundTo: (1/10))asFloat gives the Float with representation 16r3FF3333333333333 because it's rounding to a multiple of exactly 0.1, not the Float nearest to 0.1. Regards, -Martin |
> On Oct 31, 2016, at 3:58 PM, Martin McClure <[hidden email]> wrote:
> > (1.19 roundTo: (1/10))asFloat > > I should note that the final example *should* result in a Float without > having to have #asFloat sent to it. Per ANSI and traditional Smalltalk > practice, any operation where the receiver *or* the argument is a Float > produces a Float. 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. John Brant |
On 10/31/2016 02:49 PM, John Brant wrote:
>> On Oct 31, 2016, at 3:58 PM, Martin McClure <[hidden email]> wrote: >> >> (1.19 roundTo: (1/10))asFloat >> >> I should note that the final example *should* result in a Float without >> having to have #asFloat sent to it. Per ANSI and traditional Smalltalk >> practice, any operation where the receiver *or* the argument is a Float >> produces a Float. > > 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. > Thanks for the information. GemStone answers a Float. Since Fractions are more general than Floats, there is indeed a good basis for arguing that this is one of the things that ANSI got wrong. Regards, -Martin |
In reply to this post by John Brant-2
2016-10-31 22:49 GMT+01:00 John Brant <[hidden email]>: > On Oct 31, 2016, at 3:58 PM, Martin McClure <[hidden email]> wrote: Whatever result species, don't trust (aFloat roundTo: aFraction) too much, they have some chances to be inexact, except for trivial powers of two. Example: (1.105 roundTo: 1/100) -> (111/100) 1.105 < (1105/1000) -> true Though the number was smaller than exact tie (in decimal), it was rounded up. Indeed, the exact computations have a different opinion: (1.105 asFraction roundTo: 1/100) -> (11/10) That's why we must implement round: with exact computations... |
In reply to this post by wernerk
On Mon, Oct 31, 2016 at 11:10 PM, test <[hidden email]> wrote:
> Hi, > just a simple numerical example using nicolas' implementation: > 1.199999999999999999 round: 1. > "1.2" > i'd guess this result is more or less what a beginner would expect with this > line. how would he do it with roundTo:? perhaps this way? > 1.199999999999999999 roundTo: 0.1. > "1.2000000000000002" > i'm not so sure that he would immediately see that he'd need to do it this > way: > (1.199999999999999999 roundTo: (1/10))asFloat. > "1.2" > werner > On Tue, Nov 1, 2016 at 4:58 AM, Martin McClure <[hidden email]> wrote: > tl;dr: > > 1.2000000000000002 *is* the correct answer for 1.19 roundTo: 0.1. > (1.19 roundTo: (1/10))asFloat gives a different answer because it's > rounding to a multiple of exactly 0.1, not the Float nearest to 0.1. So then why don't we *really* help the naive programmer make "x roundTo: 0.1" an error? Conceptually... Number>>roundTo: quantum quantum < 1 ifTrue: [ quantum isFraction ifFalse: [ SubtleArithmeticError signal ]. ^(self / quantum) rounded * quantum SubtleArithmeticError >> defaultAction self inform: 'Decimals have an inexact Float representation, so rounding may not give you what you expect. Us Fractions instead.'. cheers -ben |
On 10/31/2016 05:07 PM, Ben Coman wrote:
> So then why don't we *really* help the naive programmer make "x > roundTo: 0.1" an error? > Conceptually... > > Number>>roundTo: quantum > quantum < 1 ifTrue: [ quantum isFraction ifFalse: [ > SubtleArithmeticError signal ]. > ^(self / quantum) rounded * quantum > > SubtleArithmeticError >> defaultAction > self inform: 'Decimals have an inexact Float representation, so > rounding may not give you what you expect. Us Fractions instead.'. > > cheers -ben > While this is tempting, this philosophy would, I'm afraid, lead to signaling this error on *all* uses of Floats, because Floats are *full* of this kind of behavior that is surprising to the uninitiated. Regards, -Martin |
In reply to this post by Martin McClure-2
Hi Martin,
thanks for this analysis, i really appreciate it. you did proof that, as you said "1.2000000000000002 *is* the correct answer for 1.19 roundTo: 0.1.". please excuse me - i seriously think it was very friendly of you to do this detailed analysis -, but my argument never was, that if i use Float>roundTo: this produces problematic floating-point-errors. if it produces floating-point-errors they wouldnt be unexpected. i thought this would be clear from my previous posts. what i tried to say is, that i am a simple user and pharo shouldnt expect from me, that i know, that if i want a result looking a bit more like 1.2, i should use "(x asFraction roundTo:(1/10))asFloat" instead of "x roundTo:0.1". the #round: method circumvents the irritating part of Float calcs imo in an inexpensive way, and rounding numbers is imo not a very exotic task, but to presume that i figure out (x asFraction roundTo:(1/10))asFloat by myself is simply expecting too much from me. otoh now i that i know how to do it, it's not a problem for me, if the majority wants to deprecate #roundTo:. Thank you again for the careful analysis werner On 10/31/2016 09:58 PM, Martin McClure wrote: > tl;dr: > > 1.2000000000000002 *is* the correct answer for 1.19 roundTo: 0.1. > (1.19 roundTo: (1/10))asFloat gives a different answer because it's > rounding to a multiple of exactly 0.1, not the Float nearest to 0.1. > > > On 10/31/2016 08:35 AM, test wrote: >> oops, make that original number 1.19 in the example. > OK, so the examples are now > > 1.19 round: 1. > > 1.19 roundTo: 0.1. > > (1.19 roundTo: (1/10))asFloat > > I should note that the final example *should* result in a Float without > having to have #asFloat sent to it. Per ANSI and traditional Smalltalk > practice, any operation where the receiver *or* the argument is a Float > produces a Float. > > Since 0.1 is not quite equal to 1/10, the correct answer may not be the > same for the latter two examples. Whether you define #round: to be one > or the other is an interesting question. > > I've learned the hard way not to trust the results from Smalltalk math > libraries too far, so let's manually figure out what the correct answer > is for each of these, and see if Pharo's doing it right. > > To start, every Float (ignoring infinities, NaNs, and subnormals) is (by > definition) a Fraction constrained to have a numerator in the range > [2**52..2**53) and a denominator that is a power of two. > > Pharo says: > 0.1 asFraction ==> (3602879701896397/36028797018963968) > > Is this correct? The numerator is less than 2**52, so this Fraction has > been reduced. Let's restore it to what it would be in its Float form by > multiplying numerator and denominator by, in this case, 2: > > 7205759403792794 > ----------------- > 72057594037927936 > > It's easy to see that this fraction is very nearly equal to 1/10, and to > see that there could be no Float closer to 1/10. > > --- > > But I haven't shown the conversion from the string '0.1' to the actual > Float instance is correct. It's possible that there's some rounding > error there, which is reversed by a rounding in a different direction by > the #asFraction. > > The Float for '0.1' is two words with values, 1069128089 and 2576980378. > Convert to hex and combine them, you get 16r3FB999999999999A > > The numerator of our fraction is the low-order 52 bits of this, with a 1 > added on the most-significant end, so 16r1999999999999A, which in > decimal is 7205759403792794. Which is what we got above, so we're good > so far. > > ======== > > Doing the same analysis on 1.19 gives a numerator of 16r130A3D70A3D70A, > and a denominator 1/16th the previous one, or > > 5359283556570890 > ---------------- > 4503599627370496 > > This one's harder, I can't just look at it and say it's the closest > possible to 1.19. > > But we know that 1.19 = 119/100. > > 119/100 * 4503599627370496/4503599627370496 = > > 535928355657089024 > ------------------ > 450359962737049600 > > and is still exactly 1.19. But to make a representable Float we have to > divide numerator and denominator by 100, rounding the numerator if > necessary. And we can see that the numerator is correctly rounded, so > Pharo also converts the string '1.19' into a Float correctly. > > How does Pharo do on > 1.19 asFraction? > > (2679641778285445/2251799813685248) > > Once again, this has been reduced by dividing numerator and denominator > by two, but it's numerically correct. > > ====== > > Now that we know that we have the correct Fractions for the floats, we > can check the rounding functions. > > 1.19 roundTo: 0.1 > should ideally be equivalent to > (1.19 asFraction roundTo: 0.1 asFraction) asFloat. > > In Pharo 5, > 1.19 asFraction roundTo: 0.1 asFraction ==> > (10808639105689191/9007199254740992) > > For this to correct, (10808639105689191/9007199254740992) must be a > multiple of (3602879701896397/36028797018963968), since that's 0.1 > asFraction. > > Is it a multiple? We can align the denominators by multiplying > (10808639105689191/9007199254740992) by 4/4, and we get > > 43234556422756764 > ----------------- > 36028797018963968 > > which would be a multiple of > > 3602879701896397 > ----------------- > 36028797018963968 > > iff 43234556422756764 is a multiple of 3602879701896397. Looking at the > original problem (1.19 roundTo: 0.1) we'd expect the multiple to be 12. > > Sure enough, 3602879701896397 * 12 ==> 43234556422756764. So we're > correct so far. > > Now we have to convert our answer to the nearest representable Float. > > Our denominator is already a power of two, but our numerator is out of > range -- it's too large. > > It's even, so we can cut it in half, getting > > 21617278211378382 > > Still too large, still even. Cut it in half again: > > 10808639105689191 > > Just a bit too large. Cut it in half again: > > 5404319552844595.5 > > Now it's in range [2**52..2**53) but it's not an integer, so we must > round. Our number is exactly halfway between two representable numbers, > so by IEEE754 we round to the even one, which is > > 5404319552844596 > > The Float we get back from > > 1.19 roundTo: 0.1 > > is 16r3FF3333333333334 > > and the numerator part of that is 16r13333333333334, or > > 5404319552844596 > > Which agrees with what we computed before. So this *is* the correct > Float result. And it prints as 1.2000000000000002. > > This print string implies that there is a Float nearer to 1.2 than this. > > 1.2 is represented as 16r3FF3333333333333, so one representable Float > less than the result of the #roundTo:. But, as we've shown, > 1.2000000000000002 is *correct*. (Which was not what I expected when > started this -- I suspected there might be rounding error in the > computation of #roundTo:. But for this example, there isn't). > > I haven't done the full analysis of it, but I expect that > (1.19 roundTo: (1/10))asFloat gives the Float with representation > 16r3FF3333333333333 because it's rounding to a multiple of exactly 0.1, > not the Float nearest to 0.1. > > Regards, > > -Martin > > |
On 11/01/2016 03:28 PM, test wrote:
> Hi Martin, > thanks for this analysis, i really appreciate it. you did proof that, > as you said "1.2000000000000002 *is* the correct answer for 1.19 > roundTo: 0.1.". please excuse me - i seriously think it was very > friendly of you to do this detailed analysis -, but my argument never > was, that if i use Float>roundTo: this produces problematic > floating-point-errors. if it produces floating-point-errors they > wouldnt be unexpected. i thought this would be clear from my previous > posts. what i tried to say is, that i am a simple user and pharo > shouldnt expect from me, that i know, that if i want a result looking > a bit more like 1.2, i should use "(x asFraction > roundTo:(1/10))asFloat" instead of "x roundTo:0.1". the #round: method > circumvents the irritating part of Float calcs imo in an inexpensive > way, and rounding numbers is imo not a very exotic task, but to > presume that i figure out (x asFraction roundTo:(1/10))asFloat by > myself is simply expecting too much from me. otoh now i that i know > how to do it, it's not a problem for me, if the majority wants to > deprecate #roundTo:. > Thank you again for the careful analysis > werner > On 10/31/2016 09:58 PM, Martin McClure wrote: >> tl;dr: >> >> 1.2000000000000002 *is* the correct answer for 1.19 roundTo: 0.1. >> (1.19 roundTo: (1/10))asFloat gives a different answer because it's >> rounding to a multiple of exactly 0.1, not the Float nearest to 0.1. >> >> >> On 10/31/2016 08:35 AM, test wrote: >>> oops, make that original number 1.19 in the example. >> OK, so the examples are now >> >> 1.19 round: 1. >> >> 1.19 roundTo: 0.1. >> >> (1.19 roundTo: (1/10))asFloat >> >> I should note that the final example *should* result in a Float without >> having to have #asFloat sent to it. Per ANSI and traditional Smalltalk >> practice, any operation where the receiver *or* the argument is a Float >> produces a Float. >> >> Since 0.1 is not quite equal to 1/10, the correct answer may not be the >> same for the latter two examples. Whether you define #round: to be one >> or the other is an interesting question. >> >> I've learned the hard way not to trust the results from Smalltalk math >> libraries too far, so let's manually figure out what the correct answer >> is for each of these, and see if Pharo's doing it right. >> >> To start, every Float (ignoring infinities, NaNs, and subnormals) is (by >> definition) a Fraction constrained to have a numerator in the range >> [2**52..2**53) and a denominator that is a power of two. >> >> Pharo says: >> 0.1 asFraction ==> (3602879701896397/36028797018963968) >> >> Is this correct? The numerator is less than 2**52, so this Fraction has >> been reduced. Let's restore it to what it would be in its Float form by >> multiplying numerator and denominator by, in this case, 2: >> >> 7205759403792794 >> ----------------- >> 72057594037927936 >> >> It's easy to see that this fraction is very nearly equal to 1/10, and to >> see that there could be no Float closer to 1/10. >> >> --- >> >> But I haven't shown the conversion from the string '0.1' to the actual >> Float instance is correct. It's possible that there's some rounding >> error there, which is reversed by a rounding in a different direction by >> the #asFraction. >> >> The Float for '0.1' is two words with values, 1069128089 and 2576980378. >> Convert to hex and combine them, you get 16r3FB999999999999A >> >> The numerator of our fraction is the low-order 52 bits of this, with a 1 >> added on the most-significant end, so 16r1999999999999A, which in >> decimal is 7205759403792794. Which is what we got above, so we're good >> so far. >> >> ======== >> >> Doing the same analysis on 1.19 gives a numerator of 16r130A3D70A3D70A, >> and a denominator 1/16th the previous one, or >> >> 5359283556570890 >> ---------------- >> 4503599627370496 >> >> This one's harder, I can't just look at it and say it's the closest >> possible to 1.19. >> >> But we know that 1.19 = 119/100. >> >> 119/100 * 4503599627370496/4503599627370496 = >> >> 535928355657089024 >> ------------------ >> 450359962737049600 >> >> and is still exactly 1.19. But to make a representable Float we have to >> divide numerator and denominator by 100, rounding the numerator if >> necessary. And we can see that the numerator is correctly rounded, so >> Pharo also converts the string '1.19' into a Float correctly. >> >> How does Pharo do on >> 1.19 asFraction? >> >> (2679641778285445/2251799813685248) >> >> Once again, this has been reduced by dividing numerator and denominator >> by two, but it's numerically correct. >> >> ====== >> >> Now that we know that we have the correct Fractions for the floats, we >> can check the rounding functions. >> >> 1.19 roundTo: 0.1 >> should ideally be equivalent to >> (1.19 asFraction roundTo: 0.1 asFraction) asFloat. >> >> In Pharo 5, >> 1.19 asFraction roundTo: 0.1 asFraction ==> >> (10808639105689191/9007199254740992) >> >> For this to correct, (10808639105689191/9007199254740992) must be a >> multiple of (3602879701896397/36028797018963968), since that's 0.1 >> asFraction. >> >> Is it a multiple? We can align the denominators by multiplying >> (10808639105689191/9007199254740992) by 4/4, and we get >> >> 43234556422756764 >> ----------------- >> 36028797018963968 >> >> which would be a multiple of >> >> 3602879701896397 >> ----------------- >> 36028797018963968 >> >> iff 43234556422756764 is a multiple of 3602879701896397. Looking at the >> original problem (1.19 roundTo: 0.1) we'd expect the multiple to be 12. >> >> Sure enough, 3602879701896397 * 12 ==> 43234556422756764. So we're >> correct so far. >> >> Now we have to convert our answer to the nearest representable Float. >> >> Our denominator is already a power of two, but our numerator is out of >> range -- it's too large. >> >> It's even, so we can cut it in half, getting >> >> 21617278211378382 >> >> Still too large, still even. Cut it in half again: >> >> 10808639105689191 >> >> Just a bit too large. Cut it in half again: >> >> 5404319552844595.5 >> >> Now it's in range [2**52..2**53) but it's not an integer, so we must >> round. Our number is exactly halfway between two representable numbers, >> so by IEEE754 we round to the even one, which is >> >> 5404319552844596 >> >> The Float we get back from >> >> 1.19 roundTo: 0.1 >> >> is 16r3FF3333333333334 >> >> and the numerator part of that is 16r13333333333334, or >> >> 5404319552844596 >> >> Which agrees with what we computed before. So this *is* the correct >> Float result. And it prints as 1.2000000000000002. >> >> This print string implies that there is a Float nearer to 1.2 than this. >> >> 1.2 is represented as 16r3FF3333333333333, so one representable Float >> less than the result of the #roundTo:. But, as we've shown, >> 1.2000000000000002 is *correct*. (Which was not what I expected when >> started this -- I suspected there might be rounding error in the >> computation of #roundTo:. But for this example, there isn't). >> >> I haven't done the full analysis of it, but I expect that >> (1.19 roundTo: (1/10))asFloat gives the Float with representation >> 16r3FF3333333333333 because it's rounding to a multiple of exactly 0.1, >> not the Float nearest to 0.1. >> >> Regards, >> >> -Martin >> >> > > > |
In reply to this post by wernerk
On 11/01/2016 07:28 AM, test wrote:
> Hi Martin, > thanks for this analysis, i really appreciate it. you did proof that, as > you said "1.2000000000000002 *is* the correct answer for 1.19 roundTo: > 0.1.". please excuse me - i seriously think it was very friendly of you > to do this detailed analysis -, but my argument never was, that if i use > Float>roundTo: this produces problematic floating-point-errors. if it > produces floating-point-errors they wouldnt be unexpected. i thought > this would be clear from my previous posts. what i tried to say is, that > i am a simple user and pharo shouldnt expect from me, that i know, that > if i want a result looking a bit more like 1.2, i should use "(x > asFraction roundTo:(1/10))asFloat" instead of "x roundTo:0.1". the > #round: method circumvents the irritating part of Float calcs imo in an > inexpensive way, and rounding numbers is imo not a very exotic task, but > to presume that i figure out (x asFraction roundTo:(1/10))asFloat by > myself is simply expecting too much from me. otoh now i that i know how > to do it, it's not a problem for me, if the majority wants to deprecate > #roundTo:. > Thank you again for the careful analysis > werner Hi Werner, Thanks for your comments. I posted the analysis because I did the analysis (and thought some others might want to see it), and I did the analysis because I wanted to find out whether that answer was right. Some Smalltalks are pretty bad in similar areas of Float handling. But aside from all the fine points, if you want a floating-point number to "look" nice and human-readable, (x asFraction roundTo:(1/10))asFloat will work, but I still recommend not rounding the number itself, but rounding the printing of the number. This is not a Pharo thing, it's an any-language-with-floats thing. In C you have printf, etc. In Pharo, you can use for instance: 1.19 printShowingDecimalPlaces: 1 ==> '1.2' This makes it easier for someone reading the code to see the intent. Regards, -Martin |
yes Martin, i get that point and i already reacted to it, i occasionally
want to calculate something with a rounded float, not print it: apart from my harley i normally use _metric screws which come in decimal steps. <friendly grin> let's end that discussion, we are going around in circles. werner On 11/02/2016 02:48 AM, Martin McClure wrote: > Hi Werner, > Thanks for your comments. I posted the analysis because I did the > analysis (and thought some others might want to see it), and I did the > analysis because I wanted to find out whether that answer was right. > Some Smalltalks are pretty bad in similar areas of Float handling. > > > But aside from all the fine points, if you want a floating-point number > to "look" nice and human-readable, > (x asFraction roundTo:(1/10))asFloat > will work, but I still recommend not rounding the number itself, but > rounding the printing of the number. This is not a Pharo thing, it's an > any-language-with-floats thing. In C you have printf, etc. In Pharo, you > can use for instance: > > 1.19 printShowingDecimalPlaces: 1 ==> '1.2' > > This makes it easier for someone reading the code to see the intent. > > Regards, > > -Martin > > |
Last thing, I'm not sure it's a good idea to deprecate round: round: has been added to overcome the rounding problems of roundTo:2016-11-02 14:40 GMT+01:00 werner kassens <[hidden email]>: yes Martin, i get that point and i already reacted to it, i occasionally want to calculate something with a rounded float, not print it: apart from my harley i normally use _metric screws which come in decimal steps. <friendly grin> let's end that discussion, we are going around in circles. |
Ok at least we should change the comment to point to
printShowingDecimalPlaces: 1.19 printShowingDecimalPlaces: 1 STf Le 2/11/16 à 17:31, Nicolas Cellier a
écrit :
|
Free forum by Nabble | Edit this page |