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