Is this a buglet? (SmallInteger>>printString related)
nicolas cellier
ncellier at ifrance.com
Wed May 30 18:03:48 UTC 2007
I used this in VW for any arbitrary large integer ,
Works even if integer cannot convert to Float because > Float maxVal.
(available at public store SYSEXT-floorLog)
Integer>>floorLog10
"Initial guess is based on digitLength and following approximation :
(2 raisedTo: 10) > (10 raisedTo: 3)"
| i j step guess n |
(self negative or: [self isZero])
ifTrue:
[^self error: 'Can''t take log of number <= 0'].
guess := (self digitLength - 1) * 8 * 3 // 10.
i := self // (10 raisedTo: guess).
step := 2.
[step > 0] whileTrue:
[n := 10 raisedTo: step.
[j := i // n.
j > 0] whileTrue:
[guess := guess + step.
i := j].
step := step // 2].
^guess
Of course, for SmallInteger, Bert's solution might be faster.
As for Float, i guess a native log10 FFI call should behave better than
self ln / 10 ln, since the latter implies 3 rounding operations (and an
inexact operation). I did not check the former however.
Nicolas
Bert Freudenberg a écrit :
> Well,
>
> (self asFloat + 0.9) log truncated + 1
>
> would work reliably for SmallIntegers.
>
> The nested conditionals might still win ... in particular if it was not
> binary search but based on frequency of numbers.
>
> - Bert -
>
> On May 30, 2007, at 15:02 , Alexander Lazarevic' wrote:
>
>> Hi Göran,
>>
>> when I wrote printStringBase: I remember I tried to use x ln / base ln
>> to get the string length with the same results as you are. Depending on
>> floats it is just not robust. I went with Stream to keep it simple. It
>> sure can help to have an optimized version for the major base rather
>> then using printStringBase: 10.
>>
>> Alex
>>
>> Göran Krampe schrieb:
>>> Hi!
>>>
>>> In playing around with SmallInteger>>printString (see
>>> bugs.squeak.org/view.php?id=6512) I tested this code for calculating the
>>> length of the String:
>>>
>>> self log truncated + 1
>>>
>>> ...but that doesn't work. The current code in my ChangeSet uses an
>>> unrolled binary search (nested ifs) which is 7x faster
>>> (#decimalDigitLength) so the above code is not something we would
>>> like to
>>> use, but I still wonder why it fails and what I would have needed to do
>>> about it to get it to work:
>>>
>>> 999 log truncated ===> 2 As expected.
>>>
>>> 1000 log ===> 3.0 As expected.
>>>
>>> 1000 log truncated ===> 2 Eh, what? Not expected!
>>>
>>> ...ok, yes, I know - Floats are the "tar pits of hell" when it comes to
>>> expected results - but... can someone answer if this is a bug or if I
>>> simply can't expect this code to work?
>>>
>>> regards, Göran
>>>
>>> PS. Strongtalk does in fact do SmallInteger>>printString almost exactly
>>> like my enhancement does (didn't peek, promise!) but does it around 5x
>>> faster than Squeak. :) I fired it up to look at how it does #log but log
>>> wasn't implemented. On the other hand Bryce tested Exupery on my code
>>> and
>>> it made a real difference - at least 2x better (not sure if he only
>>> tested
>>> printString). And then he mentioned an obvious improvement in Exupery
>>> that
>>> would make it even faster. Interesting method for comparing!
>>>
>>>
>>
>
>
>
>
>
>
More information about the Squeak-dev
mailing list
|