So here is my version for this case. I avoided changing scale and precision. Only simple multiplication with the exponent. The new part is at the end of the (current) code.
- Code: Select all
ScaledDecimal class
fromString: aString
"Answer an instance of a ScaledDecimal that is described by aString.
aString may be in
Float format (1.2e-1)
legacy format (23.76d4.2),
ANSI format (23.76s2)
or common format (23.76).
ScaledDecimal fromString: '1.2e-1'
ScaledDecimal fromString: '1.2e-2'
ScaledDecimal fromString: (1/3) asFloat printString
ScaledDecimal fromString: 1234567890123450.0 printString"
| index number sign precision scale specifiedPrecision specifiedScale |
##PR = ##'1G1JPMF'.
"Initialize our variables."
index := 1.
number := 0.
sign := 1.
scale := 0.
precision := 0.
"Consume leading spaces."
[index <= aString size and: [(aString at: index) == $ ]] whileTrue: [index := index + 1].
"Check for sign."
index <= aString size ifTrue: [
(aString at: index) == $- ifTrue: [
sign := -1.
index := index + 1]
ifFalse: [
(aString at: index) == $+ ifTrue: [index := index + 1]]].
"Collect digits before the decimal place."
[index <= aString size and: [(aString at: index) isDigit]] whileTrue: [
number := (number * 10) + (aString at: index) digitValue.
precision := precision + 1.
index := index + 1].
"Ensure we don't answer precision = scale"
precision == 0
ifTrue: [precision := 1].
"Deal with digits after the decimal place."
(index <= aString size and: [(aString at: index) == $.]) ifTrue: [
index := index + 1.
[index <= aString size and: [(aString at: index) isDigit]] whileTrue: [
number := (number * 10) + (aString at: index) digitValue.
precision := precision + 1.
scale := scale + 1.
index := index + 1]].
(index <= aString size and: [(aString at: index) == $s]) ifTrue: [ "ANSI format"
index := index + 1.
(index <= aString size and: [(aString at: index) isDigit])
ifTrue: [
specifiedScale := 0.
[index <= aString size and: [(aString at: index) isDigit]] whileTrue: [
specifiedScale := (specifiedScale * 10) + (aString at: index) digitValue.
index := index + 1]]
ifFalse: [specifiedScale := scale].
specifiedPrecision := precision - scale + specifiedScale.
^ ScaledDecimal
fromUnscaled: number
sign: sign
scale: scale
coerceToPrecision: specifiedPrecision
scale: specifiedScale].
(index <= aString size and: [(aString at: index) == $d]) ifTrue: [ "Legacy format"
specifiedPrecision := 0.
specifiedScale := scale.
index := index + 1.
(index <= aString size and: [(aString at: index) isDigit]) ifTrue: [
"Get the specified precision."
[
specifiedPrecision := (specifiedPrecision * 10) + (aString at: index) digitValue.
index := index + 1.
index <= aString size and: [(aString at: index) isDigit]]
whileTrue.
"Get the specified scale."
(index <= aString size and: [(aString at: index) == $.]) ifTrue: [
index := index + 1.
specifiedScale := 0.
[index <= aString size and: [(aString at: index) isDigit]] whileTrue: [
specifiedScale := (specifiedScale * 10) + (aString at: index) digitValue.
index := index + 1]].
^ ScaledDecimal
fromUnscaled: number
sign: sign
scale: scale
coerceToPrecision: specifiedPrecision
scale: specifiedScale]].
"*** new ***"
(index <= aString size and: [(aString at: index) == $e]) ifTrue: [ "Float format"
| exponentSign exponent |
index := index + 1.
exponentSign := 1.
"Check for sign."
index <= aString size ifTrue: [
(aString at: index) == $- ifTrue: [
exponentSign := -1.
index := index + 1] ].
(index <= aString size and: [(aString at: index) isDigit])
ifTrue: [
exponent := 0.
[index <= aString size and: [(aString at: index) isDigit]] whileTrue: [
exponent := (exponent * 10) + (aString at: index) digitValue.
index := index + 1].
exponent := exponent * exponentSign]
ifFalse: [exponent := 0].
^(exponent power: 10) * ((ScaledDecimal fromUnscaled: number sign: sign scale: scale) precision: precision)].
^(ScaledDecimal fromUnscaled: number sign: sign scale: scale) precision: precision
Juergen