LimitedPrecisionReal.st
changeset 22786 7375ac3023c4
parent 22610 f449d47f1f5c
child 22787 b4f6d9a8bf5e
equal deleted inserted replaced
22785:1d67d6adbbe5 22786:7375ac3023c4
  1247      t1 inspect. t2 inspect.
  1247      t1 inspect. t2 inspect.
  1248     "
  1248     "
  1249 ! !
  1249 ! !
  1250 
  1250 
  1251 
  1251 
  1252 
       
  1253 !LimitedPrecisionReal methodsFor:'queries'!
  1252 !LimitedPrecisionReal methodsFor:'queries'!
  1254 
  1253 
  1255 decimalPrecision
  1254 decimalPrecision
  1256     "Answer how many digits of accuracy this class supports"
  1255     "Answer how many digits of accuracy this class supports"
  1257 
  1256 
  1424    "redefined since reals are kludgy (ByteArry)"
  1423    "redefined since reals are kludgy (ByteArry)"
  1425 
  1424 
  1426    ^ 0
  1425    ^ 0
  1427 ! !
  1426 ! !
  1428 
  1427 
  1429 
       
  1430 !LimitedPrecisionReal methodsFor:'testing'!
  1428 !LimitedPrecisionReal methodsFor:'testing'!
  1431 
  1429 
  1432 isFinite
  1430 isFinite
  1433    ^ self subclassResponsibility
  1431    ^ self subclassResponsibility
  1434 
  1432 
  1555     ^ self coerce:(self truncated).
  1553     ^ self coerce:(self truncated).
  1556 
  1554 
  1557     "
  1555     "
  1558      0.4 asLongFloat truncatedAsFloat
  1556      0.4 asLongFloat truncatedAsFloat
  1559     "
  1557     "
       
  1558 !
       
  1559 
       
  1560 truncatedToPrecision
       
  1561     "truncates to the precision of the float.
       
  1562      This is slightly different from truncated.
       
  1563      Taking for example 1e32,
       
  1564      the printed representation will be 1e32,
       
  1565      but the actual value, when truncating to an integer
       
  1566      would be 100000003318135351409612647563264.
       
  1567 
       
  1568      This is due to the inaccuracy in the least significant bits,
       
  1569      and the way the print-converter compensates for this.
       
  1570      This method tries to generate an integer value which corresponds
       
  1571      to what is seen in the float's printString.
       
  1572 
       
  1573      Here, a slow fallback (generating and rescanning the printString)
       
  1574      is provided, which should work on any float number.
       
  1575      Specialized versions in subclasses may be added for more performance
       
  1576      (however, this is probably only used rarely)"
       
  1577 
       
  1578     |pow10 printString intVal s sign nFract ch expSign exp pI|
       
  1579 
       
  1580     pow10 := #(10 100 1000 10000 100000 1000000 10000000 100000000 1000000000).
       
  1581 
       
  1582     printString := self printString.
       
  1583     intVal := 0.
       
  1584     sign := 1.
       
  1585     nFract := 0.
       
  1586     exp := 0.
       
  1587 
       
  1588     "/ fetch the mantissa
       
  1589     s := printString readStream.
       
  1590     s peek == $- ifTrue:[
       
  1591         sign := -1.
       
  1592         s next.
       
  1593     ].
       
  1594     intVal := s nextDecimalInteger.
       
  1595     s peek == $. ifTrue:[
       
  1596         s next.
       
  1597         [(ch := s peek) notNil and:[ch isDigit]] whileTrue:[
       
  1598             intVal := intVal * 10 + (s next digitValue).
       
  1599             nFract := nFract + 1.
       
  1600         ].
       
  1601     ].
       
  1602     ('eEdDqQ' includes:s peek) ifTrue:[
       
  1603         expSign := 1.
       
  1604         s next.
       
  1605         (ch := s peek) == $- ifTrue:[
       
  1606             expSign := -1.
       
  1607             s next.
       
  1608         ] ifFalse:[
       
  1609             ch == $+ ifTrue:[
       
  1610                 s next.
       
  1611             ].
       
  1612         ].
       
  1613         exp := s nextDecimalInteger.
       
  1614         exp := exp * expSign.
       
  1615     ].
       
  1616     exp := exp - nFract.
       
  1617     exp < 0 ifTrue:[
       
  1618         [exp < 0] whileTrue:[
       
  1619             pI := (exp negated) min:pow10 size.
       
  1620             intVal := intVal / (pow10 at:pI).
       
  1621             exp := exp + pI.
       
  1622         ].
       
  1623         intVal := intVal asInteger.
       
  1624     ] ifFalse:[
       
  1625         [exp > 0] whileTrue:[
       
  1626             pI := exp min:pow10 size.
       
  1627             intVal := intVal * (pow10 at:pI).
       
  1628             exp := exp - pI.
       
  1629         ].
       
  1630     ].
       
  1631     ^ intVal
       
  1632 
       
  1633     "
       
  1634      1e32 asShortFloat truncated
       
  1635      1e32 asShortFloat truncatedToPrecision
       
  1636      1.234e10 asShortFloat truncatedToPrecision
       
  1637      1234e-1 asShortFloat truncatedToPrecision
       
  1638 
       
  1639      1e32 truncated
       
  1640      1e32 truncatedToPrecision
       
  1641      1.234e10 truncatedToPrecision
       
  1642      1234e-1 truncatedToPrecision
       
  1643 
       
  1644      1e32 asLongFloat truncated
       
  1645      1e32 asLongFloat truncatedToPrecision
       
  1646      1.234e10 asLongFloat truncatedToPrecision
       
  1647      1234e-1 asLongFloat truncatedToPrecision
       
  1648     "
  1560 ! !
  1649 ! !
  1561 
  1650 
  1562 !LimitedPrecisionReal methodsFor:'visiting'!
  1651 !LimitedPrecisionReal methodsFor:'visiting'!
  1563 
  1652 
  1564 acceptVisitor:aVisitor with:aParameter
  1653 acceptVisitor:aVisitor with:aParameter