 |
|
| Computers Forum Index » Computer Languages (Smalltalk) » Visualworks 7.5 fractionPart bug... |
|
Page 2 of 2 Goto page Previous 1, 2 |
|
| Author |
Message |
| nicolas cellier... |
Posted: Thu Oct 22, 2009 11:18 pm |
|
|
|
Guest
|
On 20 oct, 15:06, Aik-Siong <as... at (no spam) askoh.com> wrote:
Quote: I encountered the above problem while trying to get the base 10
mantissa of a number. How can I do that safely?
Thanks,
Aik-Siong Koh
What is the base 10 mantissa ???
BEWARE:
0.1d0 mantissa ~= 0.01d0 mantissa
If you want an ascii decimal representation of a Float fully written
in Smalltalk, see Squeak/Pharo implementation below
Be aware that converting ascii decimal -> Float (asNumber, Number
readFrom:) is also often implemented with unecessary round off
errors...
absPrintExactlyOn: aStream base: base
"Print my value on a stream in the given base. Assumes that my value
is strictly
positive; negative numbers, zero, and NaNs have already been handled
elsewhere.
Based upon the algorithm outlined in:
Robert G. Burger and R. Kent Dybvig
Printing Floating Point Numbers Quickly and Accurately
ACM SIGPLAN 1996 Conference on Programming Language Design and
Implementation
June 1996.
This version guarantees that the printed representation exactly
represents my value
by using exact integer arithmetic."
| fBase significand exp baseExpEstimate be be1 r s mPlus mMinus scale
roundingIncludesLimits d tc1 tc2 fixedFormat decPointCount slowbit
shead |
self isInfinite ifTrue: [aStream nextPutAll: 'Infinity'. ^ self].
fBase := base asFloat.
significand := self significandAsInteger.
roundingIncludesLimits := significand even.
exp := (self exponent - 52) max: MinValLogBase2.
baseExpEstimate := (self exponent * fBase reciprocalLogBase2 -
1.0e-10) ceiling.
exp >= 0
ifTrue:
[be := 1 << exp.
significand ~= 16r10000000000000
ifTrue:
[r := significand * be * 2.
s := 2.
mPlus := be.
mMinus := be]
ifFalse:
[be1 := be * 2.
r := significand * be1 * 2.
s := 4.
mPlus := be1.
mMinus := be]]
ifFalse:
[(exp = MinValLogBase2 or: [significand ~= 16r10000000000000])
ifTrue:
[r := significand * 2.
s := (1 << (exp negated)) * 2.
mPlus := 1.
mMinus := 1]
ifFalse:
[r := significand * 4.
s := (1 << (exp negated + 1)) * 2.
mPlus := 2.
mMinus := 1]].
baseExpEstimate >= 0
ifTrue: [s := s * (base raisedToInteger: baseExpEstimate)]
ifFalse:
[scale := base raisedToInteger: baseExpEstimate negated.
r := r * scale.
mPlus := mPlus * scale.
mMinus := mMinus * scale].
((r + mPlus < s) not and: [roundingIncludesLimits or: [r + mPlus >
s]])
ifTrue: [baseExpEstimate := baseExpEstimate + 1]
ifFalse:
[r := r * base.
mPlus := mPlus * base.
mMinus := mMinus * base].
(fixedFormat := baseExpEstimate between: -3 and: 6)
ifTrue:
[decPointCount := baseExpEstimate.
baseExpEstimate <= 0
ifTrue: [aStream nextPutAll: ('0.000000' truncateTo: 2 -
baseExpEstimate)]]
ifFalse:
[decPointCount := 1].
slowbit := s lowBit - 1.
shead := s >> slowbit.
[d := (r >> slowbit) // shead.
r := r - (d*s).
(tc1 := (r > mMinus) not and: [roundingIncludesLimits or: [r <
mMinus]]) |
(tc2 := (r + mPlus < s) not and: [roundingIncludesLimits or: [r +
mPlus > s]])] whileFalse:
[aStream nextPut: (Character digitValue: d).
r := r * base.
mPlus := mPlus * base.
mMinus := mMinus * base.
decPointCount := decPointCount - 1.
decPointCount = 0 ifTrue: [aStream nextPut: $.]].
tc2 ifTrue:
[(tc1 not or: [r*2 >= s]) ifTrue: [d := d + 1]].
aStream nextPut: (Character digitValue: d).
decPointCount > 0
ifTrue:
[decPointCount - 1 to: 1 by: -1 do: [:i | aStream nextPut: $0].
aStream nextPutAll: '.0'].
fixedFormat ifFalse:
[aStream nextPut: $e.
aStream nextPutAll: (baseExpEstimate - 1) printString] |
|
|
| Back to top |
|
|
|
| nicolas cellier... |
Posted: Fri Oct 23, 2009 12:05 am |
|
|
|
Guest
|
On 21 oct, 00:17, Andy Bower <bo... at (no spam) SnipThisObject-arts.com> wrote:
Quote: Cesar, Aik-Siong,
Aik-Siong escreveu:
1000.0d log fractionPart
gives 1.0d. It should be 0.0d. The error is not small. Is this a bug?
Frankly, I'd agree and say it was a bug. Whilst I know that comparing
floating point numbers can be tricky, in Dolphin:
1000.0 log fractionPart0. -> 0.
1000.0 floorLog: 10.0. -> 2.
1000.0 floorLog10. -> 3
If Dolphin can do it without issues I don't see why VisualWorks can't.
Best regards
Andy Bower
Never trust FLoat operations.
Comparing with definition of floorLog10 in exact arithmetic from
cincom public store SYSEXT-floorLog
(1.0d101) floorLog10 ~= (1.0d101) asFraction floorLog10
Both in VW76 and in Dolphin X6...
I trust second answer 100, because it is performed with exact
arithmetic (use asTrueFraction in Dolphin).
That means that binary representation of (1.0d101) is truncated...
Nicolas |
|
|
| Back to top |
|
|
|
|
|
All times are GMT
The time now is Sun Mar 21, 2010 7:29 am
|
|