FixedPoint.st
changeset 1886 7c58ef7c2d78
child 1891 58073a4e3859
equal deleted inserted replaced
1885:219c3437ad01 1886:7c58ef7c2d78
       
     1 "
       
     2      this comes from:
       
     3 
       
     4      Jan Steinman, Bytesmiths
       
     5      2002 Parkside Court, West Linn, OR 97068-2767 USA, +1 503 657 7703
       
     6      Friedlistrasse 19, CH-3006, Bern, Switzerland, +41 31 999 3946
       
     7 
       
     8      this code was published in comp.lang.smalltalk; 
       
     9      added here as an example ...
       
    10 "
       
    11 
       
    12 Fraction subclass:#FixedPoint
       
    13 	instanceVariableNames:'scale'
       
    14 	classVariableNames:''
       
    15 	poolDictionaries:''
       
    16 	category:'Magnitude-Numbers'
       
    17 !
       
    18 
       
    19 FixedPoint comment:'
       
    20 Description: This class implements infinite precision fixed-point numbers. 
       
    21 It doesn''t really do anything too interesting except creating instances, converting, and printing, 
       
    22 since its superclass Fraction does all the work.
       
    23 
       
    24 Test: "''123456789012345678901234567890.123456789'' asFixed * 1000000000 = 123456789012345678901234567890123456789"
       
    25 
       
    26 Notes: 1) The current implementation does not convert arbitrarily-based String representations, 
       
    27 	  which shouldn''t be too much a problem for financial types.'!
       
    28 
       
    29 !FixedPoint class methodsFor:'documentation'!
       
    30 
       
    31 copyright
       
    32 "
       
    33      this comes from:
       
    34 
       
    35      Jan Steinman, Bytesmiths
       
    36      2002 Parkside Court, West Linn, OR 97068-2767 USA, +1 503 657 7703
       
    37      Friedlistrasse 19, CH-3006, Bern, Switzerland, +41 31 999 3946
       
    38 
       
    39      this code was published in comp.lang.smalltalk; 
       
    40      added here as an example ...
       
    41 "
       
    42 !
       
    43 
       
    44 documentation
       
    45 "
       
    46     Description: This class implements infinite precision fixed-point numbers,
       
    47     which internally hold exact (fractional) results, but print themself with
       
    48     a limited number of digits after the decimal point. 
       
    49     These can be used in computation, where rounding errors should not accumulate,
       
    50     but only a limited precision is required for the final result.
       
    51 
       
    52     It doesn't really do anything too interesting except creating instances, 
       
    53     converting, and printing, since its superclass Fraction does all the work.
       
    54 
       
    55     Test: 
       
    56         '123456789012345678901234567890.123456789' asFixed * 1000000000
       
    57         -> 123456789012345678901234567890123456789'
       
    58 
       
    59     Notes: 1) The current implementation does not convert arbitrarily-based 
       
    60               String representations, which shouldn't be too much a problem 
       
    61               for financial types.
       
    62 
       
    63            2) the implementation is a hack - it has not been optimized for speed
       
    64               in particular.
       
    65 
       
    66     [author:]
       
    67         Jan Steinman, Bytesmiths
       
    68         modified & enhanced by Claus Gittinger
       
    69 
       
    70     [see also:]
       
    71         Integer Float Number
       
    72 "
       
    73 !
       
    74 
       
    75 examples
       
    76 "
       
    77                                                                 [exBegin]
       
    78      |a b r|
       
    79 
       
    80      a := (FixedPoint fromString:'123.456').
       
    81      b := (FixedPoint fromString:'1.10').
       
    82      r := a + b.
       
    83      Transcript showCR:r.
       
    84      Transcript showCR:(r withScale:2).
       
    85      Transcript showCR:(r withScale:1).
       
    86      Transcript showCR:(r rounded).
       
    87                                                                 [exEnd]
       
    88 
       
    89                                                                 [exBegin]
       
    90      |a b r|
       
    91 
       
    92      a := (FixedPoint fromString:'0.9999999').
       
    93      b := (FixedPoint fromString:'0.0000001').
       
    94      r := a + b.
       
    95      Transcript showCR:r.
       
    96      Transcript showCR:(r withScale:2).
       
    97      Transcript showCR:(r withScale:1).
       
    98      Transcript showCR:(r rounded).
       
    99                                                                 [exEnd]
       
   100 
       
   101                                                                 [exBegin]
       
   102      |a b r|
       
   103 
       
   104      a := (FixedPoint fromString:'0.9999998').
       
   105      b := (FixedPoint fromString:'0.0000001').
       
   106      r := a + b.
       
   107      Transcript showCR:r.
       
   108      Transcript showCR:(r withScale:2).
       
   109      Transcript showCR:(r withScale:1).
       
   110      Transcript showCR:(r rounded).
       
   111                                                                 [exEnd]
       
   112 
       
   113                                                                 [exBegin]
       
   114      |a b r|
       
   115 
       
   116      a := (FixedPoint fromString:'1.0').
       
   117      b := (FixedPoint fromString:'0.0000001').
       
   118      r := a + b.
       
   119      Transcript showCR:r.
       
   120      Transcript showCR:(r withScale:2).
       
   121      Transcript showCR:(r withScale:1).
       
   122      Transcript showCR:(r rounded).
       
   123                                                                 [exEnd]
       
   124 
       
   125                                                                 [exBegin]
       
   126      |a b r|
       
   127 
       
   128      a := (FixedPoint fromString:'0.99').
       
   129      b := (FixedPoint fromString:'0.0000001').
       
   130      r := a + b.
       
   131      Transcript showCR:r.
       
   132      Transcript showCR:(r withScale:2).
       
   133      Transcript showCR:(r withScale:1).
       
   134      Transcript showCR:(r rounded).
       
   135                                                                 [exEnd]
       
   136 
       
   137 "
       
   138 ! !
       
   139 
       
   140 !FixedPoint class methodsFor:'instance creation'!
       
   141 
       
   142 fromString: fixedPointString
       
   143     "Answer a new instance of the receiver which is an interpretation of the digits found in <fixedPointString>."
       
   144 
       
   145     ^self readFrom: (ReadStream on: fixedPointString)
       
   146 
       
   147     "
       
   148      Fixed fromString:'123.456'
       
   149     "
       
   150 !
       
   151 
       
   152 numerator:n denominator:d scale:s
       
   153     ^ self basicNew
       
   154         setNumerator:n
       
   155         denominator:d
       
   156         scale:s
       
   157 !
       
   158 
       
   159 readFrom:aStream 
       
   160     "return an instance of me as described on the stream, aStream."
       
   161 
       
   162     | sign integerPart fractionStream char fractionPart scale |
       
   163 
       
   164     aStream peek == $- ifTrue:[
       
   165         sign := -1.
       
   166         aStream next.
       
   167     ] ifFalse:[
       
   168         sign := 1
       
   169     ].
       
   170 
       
   171     (aStream atEnd or:[aStream peek isLetter]) ifTrue: [^0].
       
   172 
       
   173     integerPart := (aStream upTo:$.) asNumber.
       
   174     (aStream atEnd or: [aStream peek isLetter]) ifTrue: [^integerPart].
       
   175 
       
   176     fractionStream := ReadWriteStream on:(String new: 10).
       
   177     [
       
   178         char := aStream next.
       
   179         char ~~ nil and:[char isDigit]
       
   180     ] whileTrue:[
       
   181         fractionStream nextPut:char
       
   182     ].
       
   183 
       
   184     scale := fractionStream contents size.
       
   185     fractionPart := Number readFromString:(fractionStream contents).
       
   186 
       
   187     ^ self basicNew 
       
   188         setNumerator:(integerPart * (10 raisedTo:scale) + fractionPart) * sign
       
   189         scale:scale
       
   190 
       
   191     "
       
   192      Fixed readFrom:('123.456' readStream) 
       
   193      Fixed readFrom:('-123.456' readStream) 
       
   194     "
       
   195 ! !
       
   196 
       
   197 !FixedPoint methodsFor:'accessing'!
       
   198 
       
   199 scale
       
   200     "Return the number of places of significance that is carried by the receiver."
       
   201 
       
   202     ^ scale
       
   203 !
       
   204 
       
   205 withScale:newScale
       
   206     "Return a copy of the receiver, with newScale number of post-decimal
       
   207      digits"
       
   208 
       
   209     ^ self class
       
   210         numerator:numerator
       
   211         denominator:denominator
       
   212         scale:newScale
       
   213 
       
   214     "
       
   215      (Fixed fromString:'12345.12345') withScale:2 
       
   216 
       
   217      ((Fixed fromString:'0.33333333')
       
   218       + 
       
   219       (Fixed fromString:'0.33333333')
       
   220      ) withScale:2   
       
   221     "
       
   222 ! !
       
   223 
       
   224 !FixedPoint methodsFor:'arithmetic'!
       
   225 
       
   226 * aNumber
       
   227     "return the product of the receiver and the argument, aNumber.
       
   228      Redefined to care for the scale if the argument is another fixPoint number.
       
   229      The results scale is the maximum of the receivers scale and the arguments
       
   230      scale."
       
   231 
       
   232     |n d sMax|
       
   233 
       
   234     (aNumber isMemberOf:SmallInteger) ifTrue:[
       
   235         ^ self class 
       
   236                 numerator:(numerator * aNumber)
       
   237                 denominator:denominator
       
   238                 scale:scale
       
   239     ].
       
   240     (aNumber isMemberOf:self class) ifTrue:[
       
   241         n := numerator * aNumber numerator.
       
   242         d := denominator * aNumber denominator.
       
   243         sMax := scale max:aNumber scale.
       
   244 
       
   245         ^ self class 
       
   246             numerator:n 
       
   247             denominator:d
       
   248             scale:sMax
       
   249     ].
       
   250     ^ aNumber productFromFixedPoint:self
       
   251 
       
   252     "                       
       
   253      |a r|
       
   254 
       
   255      a := (FixedPoint fromString:'123.456').
       
   256      r := a * 5.    
       
   257      Transcript showCR:r.    
       
   258      Transcript showCR:(r withScale:2).
       
   259     "
       
   260 
       
   261     "                       
       
   262      |a b r|
       
   263 
       
   264      a := (FixedPoint fromString:'123.456').
       
   265      b := (FixedPoint fromString:'1.10').
       
   266      r := a * b.    
       
   267      Transcript showCR:r.    
       
   268      Transcript showCR:(r withScale:2).
       
   269     "
       
   270 
       
   271     "                       
       
   272      |a b r|
       
   273 
       
   274      a := (FixedPoint fromString:'123.456').
       
   275      b := (FixedPoint fromString:'-1.10').
       
   276      r := a * b.    
       
   277      Transcript showCR:r.    
       
   278      Transcript showCR:(r withScale:2).
       
   279     "
       
   280 
       
   281     "
       
   282      |a b r|
       
   283 
       
   284      a := (FixedPoint fromString:'0.9999999').
       
   285      b := (FixedPoint fromString:'0.9999999').
       
   286      r := a * b.    
       
   287      Transcript show:'fixed (exact)  : '; showCR:r.    
       
   288      Transcript show:'fixed (scale2) : '; showCR:(r withScale:2).
       
   289 
       
   290      Transcript show:'float (inexact): '; showCR:(0.9999999 * 0.9999999).
       
   291     "
       
   292 
       
   293     "
       
   294      |a b r|
       
   295 
       
   296      a := 1.
       
   297      b := (FixedPoint fromString:'0.9999999').
       
   298      r := a * b.    
       
   299      Transcript show:'fixed (exact)  : '; showCR:r.    
       
   300      Transcript show:'fixed (scale2) : '; showCR:(r withScale:2).
       
   301 
       
   302      Transcript show:'float (inexact): '; showCR:(0.9999999 * 0.9999999).
       
   303     "
       
   304 
       
   305 
       
   306 !
       
   307 
       
   308 + aNumber
       
   309     "return the sum of the receiver and the argument, aNumber.
       
   310      Redefined to care for the scale if the argument is another fixPoint number.
       
   311      The resulting scale will be the maximum of the receivers and the
       
   312      arguments scale."
       
   313 
       
   314     |n d sMax|
       
   315 
       
   316     (aNumber isMemberOf:self class) ifTrue:[
       
   317         n := aNumber numerator.
       
   318         d := aNumber denominator.
       
   319         sMax := scale max:aNumber scale.
       
   320 
       
   321         "save a multiplication if possible"
       
   322         denominator == d ifTrue:[
       
   323             ^ self class 
       
   324                 numerator:(numerator + n) 
       
   325                 denominator:d
       
   326                 scale:sMax
       
   327         ].
       
   328 
       
   329         ^ self class 
       
   330                 numerator:((numerator * d) + (n * denominator))
       
   331                 denominator:(denominator * d)
       
   332                 scale:sMax
       
   333     ].
       
   334     ^ aNumber sumFromFixedPoint:self
       
   335 
       
   336     "
       
   337      |a b|
       
   338 
       
   339      a := (FixedPoint fromString:'123.456').
       
   340      b := (FixedPoint fromString:'1.10').
       
   341      a + b
       
   342     "
       
   343 
       
   344     "
       
   345      |a b|
       
   346 
       
   347      a := (FixedPoint fromString:'0.9999999').
       
   348      b := (FixedPoint fromString:'0.0000001').
       
   349      a + b                   
       
   350     "
       
   351 
       
   352     "
       
   353      |a b|
       
   354 
       
   355      a := (FixedPoint fromString:'0.99').
       
   356      b := (FixedPoint fromString:'0.0000001').
       
   357      a + b                             
       
   358     "
       
   359 
       
   360     "
       
   361      |a b|
       
   362 
       
   363      a := (FixedPoint fromString:'0.99').
       
   364      b := (FixedPoint fromString:'0.0000001').
       
   365      (a + b) withScale:2  
       
   366     "
       
   367 
       
   368     "
       
   369      |a b|
       
   370 
       
   371      a := (FixedPoint fromString:'0.99').
       
   372      b := (FixedPoint fromString:'0.0000001').
       
   373      (a + b) withScale:1  
       
   374     "
       
   375 
       
   376     "
       
   377      |a b|
       
   378 
       
   379      a := 1.
       
   380      b := (FixedPoint fromString:'0.0000001').
       
   381      Transcript showCR:((a + b) withScale:1).
       
   382      Transcript showCR:(a + b)
       
   383     "
       
   384 
       
   385 
       
   386 !
       
   387 
       
   388 - aNumber
       
   389     "return the difference of the receiver and the argument, aNumber.
       
   390      Redefined to care for the scale if the argument is another fixPoint number.
       
   391      The results scale is the maximum of the receivers scale and the arguments
       
   392      scale."
       
   393 
       
   394     |n d sMax|
       
   395 
       
   396     (aNumber isMemberOf:self class) ifTrue:[
       
   397         n := aNumber numerator.
       
   398         d := aNumber denominator.
       
   399         sMax := scale max:aNumber scale.
       
   400 
       
   401         "save a multiplication if possible"
       
   402         denominator == d ifTrue:[
       
   403             ^ self class 
       
   404                 numerator:(numerator - n) 
       
   405                 denominator:d
       
   406                 scale:sMax
       
   407         ].
       
   408 
       
   409         ^ self class 
       
   410                 numerator:((numerator * d) - (n * denominator))
       
   411                 denominator:(denominator * d)
       
   412                 scale:sMax
       
   413     ].
       
   414     ^ aNumber differenceFromFixedPoint:self
       
   415 
       
   416     "
       
   417      |a b|
       
   418 
       
   419      a := (FixedPoint fromString:'123.456').
       
   420      b := (FixedPoint fromString:'1.10').
       
   421      a - b    
       
   422     "
       
   423 
       
   424     "
       
   425      |a b|
       
   426 
       
   427      a := (FixedPoint fromString:'0.9999999').
       
   428      b := (FixedPoint fromString:'0.0000009').
       
   429      a - b                   
       
   430     "
       
   431 
       
   432     "
       
   433      |a b|
       
   434 
       
   435      a := (FixedPoint fromString:'0.99').
       
   436      b := (FixedPoint fromString:'0.0000001').
       
   437      a - b                          
       
   438     "
       
   439 
       
   440     "
       
   441      |a b|
       
   442 
       
   443      a := (FixedPoint fromString:'0.99').
       
   444      b := (FixedPoint fromString:'0.0000001').
       
   445      (a - b) withScale:2  
       
   446     "
       
   447 
       
   448     "
       
   449      |a b|
       
   450 
       
   451      a := (FixedPoint fromString:'0.99').
       
   452      b := (FixedPoint fromString:'0.0000001').
       
   453      (a - b) withScale:1  
       
   454     "
       
   455 
       
   456     "
       
   457      |a b|
       
   458 
       
   459      a := (FixedPoint fromString:'0.0000001').
       
   460      b := (FixedPoint fromString:'0.99').
       
   461      (a - b) withScale:2   
       
   462     "
       
   463 
       
   464     "
       
   465      |a b|
       
   466 
       
   467      a := 1.
       
   468      b := (FixedPoint fromString:'0.0000001').
       
   469      Transcript showCR:((a - b) withScale:1).
       
   470      Transcript showCR:(a - b)
       
   471     "
       
   472 
       
   473 !
       
   474 
       
   475 / aNumber
       
   476     "return the quotien of the receiver and the argument, aNumber.
       
   477      Redefined to care for the scale if the argument is another fixPoint number.
       
   478      The results scale is the maximum of the receivers scale and the arguments
       
   479      scale."
       
   480 
       
   481     |n d sMax|
       
   482 
       
   483     (aNumber isMemberOf:SmallInteger) ifTrue:[
       
   484         ^ (self class 
       
   485                 numerator:numerator
       
   486                 denominator:(denominator * aNumber)
       
   487                 scale:scale) reduced
       
   488     ].
       
   489 
       
   490     (aNumber isMemberOf:self class) ifTrue:[
       
   491         n := numerator * aNumber denominator.
       
   492         d := denominator * aNumber numerator.
       
   493         sMax := scale max:aNumber scale.
       
   494 
       
   495         ^ (self class 
       
   496             numerator:n 
       
   497             denominator:d
       
   498             scale:sMax) reduced
       
   499     ].
       
   500     ^ aNumber quotientFromFixedPoint:self
       
   501 
       
   502     "                       
       
   503      |a r|                     
       
   504 
       
   505      a := (FixedPoint fromString:'123.456').
       
   506      r := a / 5.    
       
   507      Transcript showCR:r.    
       
   508      Transcript showCR:(r withScale:2).
       
   509      Transcript showCR:(r withScale:9).
       
   510     "
       
   511 
       
   512     "                       
       
   513      |a b r|
       
   514 
       
   515      a := (FixedPoint fromString:'123.456').
       
   516      b := (FixedPoint fromString:'1.10').
       
   517      r := a / b.    
       
   518      Transcript showCR:r.    
       
   519      Transcript showCR:(r withScale:2).
       
   520     "
       
   521 
       
   522     "                       
       
   523      |a b r|
       
   524 
       
   525      a := (FixedPoint fromString:'-123.456').
       
   526      b := (FixedPoint fromString:'-1.10').
       
   527      r := a / b.    
       
   528      Transcript showCR:r.    
       
   529      Transcript showCR:(r withScale:2).
       
   530     "
       
   531 
       
   532     "                       
       
   533      |a b r|
       
   534 
       
   535      a := (FixedPoint fromString:'123.456').
       
   536      b := (FixedPoint fromString:'-1.10').
       
   537      r := a / b.    
       
   538      Transcript showCR:r.    
       
   539      Transcript showCR:(r withScale:2).
       
   540     "
       
   541 
       
   542     "
       
   543      |a b r|
       
   544 
       
   545      a := 1.
       
   546      b := (FixedPoint fromString:'0.9999999').
       
   547      r := a / b.    
       
   548      Transcript show:'fixed (exact)  : '; showCR:r.    
       
   549      Transcript show:'fixed (scale2) : '; showCR:(r withScale:2).
       
   550 
       
   551      Transcript show:'float (inexact): '; showCR:(1 / 0.9999999).
       
   552     "
       
   553 ! !
       
   554 
       
   555 !FixedPoint methodsFor:'coercing & converting'!
       
   556 
       
   557 asFixedPoint
       
   558     "return the receiver as a fixedPoint number"
       
   559 
       
   560     ^ self
       
   561 
       
   562 !
       
   563 
       
   564 asFraction
       
   565     "return the receiver as a fraction"
       
   566 
       
   567     ^ (Fraction
       
   568         numerator:numerator
       
   569         denominator:denominator) reduced
       
   570 
       
   571     "
       
   572      (FixedPoint fromString:'0.2')           
       
   573      (FixedPoint fromString:'0.2') asFraction
       
   574      (FixedPoint fromString:'0.2') asFloat
       
   575      (FixedPoint fromString:'0.2') asShortFloat
       
   576      (FixedPoint fromString:'0.2') asInteger
       
   577     "
       
   578 !
       
   579 
       
   580 coerce:aNumber
       
   581     "return aNumber converted into receivers type"
       
   582 
       
   583     ^ aNumber asFixedPoint
       
   584 
       
   585 !
       
   586 
       
   587 generality
       
   588     "return the generality value - see ArithmeticValue>>retry:coercing:"
       
   589 
       
   590     ^ 65
       
   591 
       
   592     "
       
   593      (FixedPoint fromString:'1.001') + 1      
       
   594      (FixedPoint fromString:'1.001') + 1.0    
       
   595      (FixedPoint fromString:'1.001') + (1/2)   
       
   596      (FixedPoint fromString:'1.001') + 1.0 asShortFloat 
       
   597      (FixedPoint fromString:'1.001') + 1 asLargeInteger 
       
   598 
       
   599      1 + (FixedPoint fromString:'1.001') 
       
   600      1.0 + (FixedPoint fromString:'1.001')
       
   601      (1/2) + (FixedPoint fromString:'1.001')
       
   602      1.0 asShortFloat + (FixedPoint fromString:'1.001')
       
   603      1 asLargeInteger + (FixedPoint fromString:'1.001')
       
   604     "
       
   605 ! !
       
   606 
       
   607 !FixedPoint methodsFor:'double dispatching'!
       
   608 
       
   609 differenceFromInteger:anInteger
       
   610     "sent when an integer does not know how to subtract the receiver.
       
   611      Redefined here to preserve the scale."
       
   612 
       
   613     ^ (self class 
       
   614         numerator:((anInteger * denominator) - numerator)
       
   615         denominator:denominator
       
   616         scale:scale) reduced
       
   617 
       
   618 !
       
   619 
       
   620 productFromInteger:anInteger
       
   621     "sent when an integer does not know how to multiply the receiver.
       
   622      Redefined here to preserve the scale."
       
   623 
       
   624     ^ (self class 
       
   625         numerator:(anInteger * numerator)
       
   626         denominator:denominator
       
   627         scale:scale) reduced
       
   628 
       
   629     "Modified: 5.11.1996 / 10:32:28 / cg"
       
   630 
       
   631 
       
   632 !
       
   633 
       
   634 quotientFromInteger:anInteger
       
   635     "sent when an integer does not know how to divide by the receiver.
       
   636      Redefined here to preserve the scale."
       
   637 
       
   638     ^ (self class 
       
   639         numerator:(anInteger * denominator)
       
   640         denominator:numerator
       
   641         scale:scale) reduced
       
   642 
       
   643     "Modified: 5.11.1996 / 10:32:35 / cg"
       
   644 
       
   645 
       
   646 !
       
   647 
       
   648 sumFromInteger:anInteger
       
   649     "sent when an integer does not know how to add the receiver.
       
   650      Redefined here to preserve the scale."
       
   651 
       
   652     ^ (self class 
       
   653         numerator:(numerator + (anInteger * denominator))
       
   654         denominator:denominator
       
   655         scale:scale) reduced
       
   656 
       
   657     "Modified: 5.11.1996 / 10:32:43 / cg"
       
   658 
       
   659 
       
   660 ! !
       
   661 
       
   662 !FixedPoint methodsFor:'printing'!
       
   663 
       
   664 printOn: aStream 
       
   665     "Append to the argument, aStream, a printed representation of the receiver.
       
   666      For printout, only scale post-decimal digits are printed
       
   667      (and the printout is rounded to that many digits)"
       
   668 
       
   669     |e decimals integerPart fractionPart negative num|
       
   670 
       
   671     numerator < 0 ifTrue:[
       
   672         negative := true.
       
   673         num := numerator negated.
       
   674     ] ifFalse:[
       
   675         negative := false.
       
   676         num := numerator.
       
   677     ].
       
   678     integerPart := (num // denominator).
       
   679     e := 10 raisedTo:scale.
       
   680     fractionPart := (num \\ denominator).
       
   681 
       
   682     "/ the most common case is a denominator fitting the scale
       
   683     "/ (fixedPoint numbers are created this way)
       
   684 
       
   685     e == denominator ifFalse:[
       
   686         fractionPart := fractionPart * (e * 10) // denominator.
       
   687         fractionPart := (fractionPart roundTo:10) // 10.
       
   688 
       
   689         fractionPart >= e ifTrue:[
       
   690             integerPart := integerPart + 1.
       
   691             fractionPart := 0.
       
   692         ]
       
   693     ].
       
   694 
       
   695     "/
       
   696     "/ add a 1000..., so we can (mis-)use integer-printString ...
       
   697     "/ the highest-1 will be cutoff after padding.
       
   698     "/
       
   699     fractionPart := e + fractionPart.
       
   700 
       
   701     negative ifTrue:[
       
   702         aStream nextPut:$-
       
   703     ].
       
   704     integerPart printOn:aStream.
       
   705     aStream nextPut: $..
       
   706     ((fractionPart printStringPaddedTo:scale with:$0) copyFrom:2) printOn:aStream
       
   707 
       
   708     "
       
   709      (FixedPoint fromString:'0.66666666')               
       
   710      (FixedPoint fromString:'0.66666666') withScale:2   
       
   711      (FixedPoint fromString:'0.99999999')               
       
   712      (FixedPoint fromString:'0.99999999') withScale:2   
       
   713      (FixedPoint fromString:'1.00000001')               
       
   714      (FixedPoint fromString:'1.00000001') withScale:2   
       
   715      (FixedPoint fromString:'1.005')                    
       
   716      (FixedPoint fromString:'1.005') withScale:2        
       
   717      (FixedPoint fromString:'1.005') withScale:1        
       
   718 
       
   719      (FixedPoint fromString:'-0.66666666')              
       
   720      (FixedPoint fromString:'-0.66666666') withScale:2   
       
   721      (FixedPoint fromString:'-0.99999999')              
       
   722      (FixedPoint fromString:'-0.99999999') withScale:2   
       
   723      (FixedPoint fromString:'-1.00000001')              
       
   724      (FixedPoint fromString:'-1.00000001') withScale:2   
       
   725      (FixedPoint fromString:'-1.005')                   
       
   726      (FixedPoint fromString:'-1.005') withScale:2       
       
   727      (FixedPoint fromString:'-1.005') withScale:1       
       
   728      (FixedPoint fromString:'-1.05')                    
       
   729      (FixedPoint fromString:'-1.05') withScale:2      
       
   730      (FixedPoint fromString:'-1.05') withScale:1      
       
   731      (FixedPoint fromString:'-1.04')                  
       
   732      (FixedPoint fromString:'-1.04') withScale:2      
       
   733      (FixedPoint fromString:'-1.04') withScale:1      
       
   734     "
       
   735 
       
   736     "
       
   737      |a b r|
       
   738 
       
   739      a := (FixedPoint fromString:'0.66666666') withScale:2.
       
   740      b := (FixedPoint fromString:'0.33333333').
       
   741      r := (a + b) withScale:4.
       
   742      Transcript show:'printout with scale of 4 :'; showCR:r.
       
   743      Transcript show:'more precise value       :'; showCR:(r withScale:8)
       
   744     "
       
   745 ! !
       
   746 
       
   747 !FixedPoint methodsFor:'private'!
       
   748 
       
   749 reduced
       
   750     |gc|
       
   751 
       
   752     scale isNil ifTrue:[
       
   753         "/ to catch inherited Fraction reduce calls
       
   754         self error:'should not happen'.
       
   755         scale := 3
       
   756     ].
       
   757 
       
   758     denominator == 1 ifTrue:[^ numerator].
       
   759     numerator == 1 ifTrue:[^ self].
       
   760     numerator == 0 ifTrue:[^ 0].
       
   761 
       
   762     gc := numerator gcd:denominator.
       
   763     gc := gc gcd:(10 raisedTo:scale).
       
   764 
       
   765     (gc == 1) ifFalse:[
       
   766         numerator := numerator // gc.
       
   767         denominator := denominator // gc
       
   768     ].
       
   769 
       
   770     (numerator < 0) ifTrue:[
       
   771         (denominator < 0) ifTrue:[
       
   772             numerator := numerator negated.
       
   773             denominator := denominator negated
       
   774         ]
       
   775     ].
       
   776     (denominator == 1) ifTrue:[^ numerator].
       
   777     ^ self
       
   778 
       
   779 !
       
   780 
       
   781 setNumerator:nInteger denominator:d scale:s 
       
   782     "Initialize the instance variables."
       
   783 
       
   784     scale := s.
       
   785     super
       
   786         setNumerator:nInteger 
       
   787         denominator:d
       
   788 !
       
   789 
       
   790 setNumerator:nInteger scale:s 
       
   791     "Initialize the instance variables."
       
   792 
       
   793     scale := s.
       
   794     super
       
   795         setNumerator:nInteger 
       
   796         denominator:(10 raisedTo:s)
       
   797 !
       
   798 
       
   799 setScale:newScale 
       
   800     "Initialize the scale instance variables."
       
   801 
       
   802     scale := newScale.
       
   803 ! !
       
   804 
       
   805 !FixedPoint class methodsFor:'documentation'!
       
   806 
       
   807 version
       
   808     ^ '$Header: /cvs/stx/stx/libbasic/FixedPoint.st,v 1.1 1996-11-05 18:17:56 cg Exp $'
       
   809 ! !