Fraction.st
changeset 1 a27a279701f8
child 2 6526dde5f3ac
equal deleted inserted replaced
0:aa2498ef6470 1:a27a279701f8
       
     1 "
       
     2  COPYRIGHT (c) 1989-93 by Claus Gittinger
       
     3               All Rights Reserved
       
     4 
       
     5  This software is furnished under a license and may be used
       
     6  only in accordance with the terms of that license and with the
       
     7  inclusion of the above copyright notice.   This software may not
       
     8  be provided or otherwise made available to, or used by, any
       
     9  other person.  No title to or ownership of the software is
       
    10  hereby transferred.
       
    11 "
       
    12 
       
    13 Number subclass:#Fraction
       
    14        instanceVariableNames:'numerator denominator'
       
    15        classVariableNames:'FractionOne FractionZero'
       
    16        poolDictionaries:''
       
    17        category:'Magnitude-Numbers'
       
    18 !
       
    19 
       
    20 Fraction comment:'
       
    21 
       
    22 COPYRIGHT (c) 1989-93 by Claus Gittinger
       
    23               All Rights Reserved
       
    24 
       
    25 %W% %E%
       
    26 '!
       
    27 
       
    28 !Fraction class methodsFor:'initialization'!
       
    29 
       
    30 initialize
       
    31     FractionZero := self numerator:0 denominator:1.
       
    32     FractionOne := self numerator:1 denominator:1
       
    33 ! !
       
    34 
       
    35 !Fraction class methodsFor:'constants'!
       
    36 
       
    37 zero
       
    38     ^ FractionZero
       
    39 !
       
    40 
       
    41 unity
       
    42     ^ FractionOne
       
    43 ! !
       
    44 
       
    45 !Fraction class methodsFor:'instance creation'!
       
    46 
       
    47 new
       
    48     "create and return a new fraction with value 0"
       
    49 
       
    50     ^ self basicNew setNumerator:0 denominator:1
       
    51 !
       
    52 
       
    53 numerator:num denominator:den
       
    54     "create and return a new fraction with numerator num and denominator den"
       
    55 
       
    56 %{  /* NOCONTEXT */
       
    57     extern char *newNextPtr, *newEndPtr;
       
    58 
       
    59     if (self == Fraction) {
       
    60         if (_CanDoQuickNew(sizeof(struct fractionstruct))) {
       
    61             OBJ newFraction;
       
    62 
       
    63             _qCheckedAlignedNew(newFraction, sizeof(struct fractionstruct), __context);
       
    64             _InstPtr(newFraction)->o_class = Fraction;
       
    65             _FractionInstPtr(newFraction)->f_numerator = num;
       
    66             _FractionInstPtr(newFraction)->f_denominator = den;
       
    67             /* no store check needed - its definitely in newSpace */
       
    68             RETURN ( newFraction );
       
    69         }
       
    70     }
       
    71 %}
       
    72 .
       
    73     ^ self basicNew setNumerator:num denominator:den
       
    74 ! !
       
    75 
       
    76 !Fraction methodsFor:'accessing'!
       
    77 
       
    78 numerator
       
    79     "return the numerator"
       
    80 
       
    81     ^ numerator
       
    82 !
       
    83 
       
    84 denominator
       
    85     "return the denominator"
       
    86 
       
    87     ^ denominator
       
    88 ! !
       
    89 
       
    90 !Fraction methodsFor:'private'!
       
    91 
       
    92 setNumerator:num denominator:den
       
    93     "set both numerator and denominator"
       
    94 
       
    95     numerator := num.
       
    96     denominator := den
       
    97 !
       
    98 
       
    99 reduced
       
   100     "reduce the receiver"
       
   101 
       
   102     |gc|
       
   103 
       
   104     denominator == 1 ifTrue:[^ numerator].
       
   105     numerator == 1 ifTrue:[^ self].
       
   106 
       
   107     gc := numerator gcd:denominator.
       
   108     (gc == 1) ifFalse:[
       
   109         numerator := numerator // gc.
       
   110         denominator := denominator // gc
       
   111     ].
       
   112     (numerator < 0) ifTrue:[
       
   113         (denominator < 0) ifTrue:[
       
   114             numerator := numerator negated.
       
   115             denominator := denominator negated
       
   116         ]
       
   117     ].
       
   118     (denominator == 1) ifTrue:[^ numerator].
       
   119     ^ self
       
   120 ! !
       
   121 
       
   122 !Fraction methodsFor:'coercing'!
       
   123 
       
   124 coerce:aNumber
       
   125     ^ aNumber asFraction
       
   126 !
       
   127 
       
   128 generality
       
   129     ^ 60
       
   130 ! !
       
   131 
       
   132 !Fraction methodsFor:'converting'!
       
   133 
       
   134 asInteger
       
   135     "return an integer with my value - will usually truncate"
       
   136 
       
   137     ^ numerator // denominator
       
   138 !
       
   139 
       
   140 asLargeInteger
       
   141     "return an integer with my value - will usually truncate"
       
   142 
       
   143     ^ self asInteger asLargeInteger
       
   144 !
       
   145 
       
   146 asFloat
       
   147     "return a float with (approximately) my value"
       
   148 
       
   149     ^ (numerator asFloat) / (denominator asFloat)
       
   150 !
       
   151 
       
   152 asFraction
       
   153     "return the receiver as fraction - thats itself"
       
   154 
       
   155     ^ self
       
   156 ! !
       
   157 
       
   158 !Fraction methodsFor:'comparing'!
       
   159 
       
   160 = aNumber
       
   161     "return true, if the argument represents the same numeric value
       
   162      as the receiver, false otherwise"
       
   163 
       
   164     (aNumber isMemberOf:SmallInteger) ifTrue:[
       
   165         (denominator = 1) ifFalse:[^ false].
       
   166         ^ numerator = aNumber
       
   167     ].
       
   168     (aNumber isKindOf:Fraction) ifTrue:[
       
   169         (numerator = aNumber numerator) ifFalse:[^ false].
       
   170         ^ denominator = aNumber denominator
       
   171     ].
       
   172     ^ self retry:#= coercing:aNumber
       
   173 !
       
   174 
       
   175 > aNumber
       
   176     "return true if the receiver is greater
       
   177      than aNumber, false otherwise."
       
   178     "optional - could use inherited method ..."
       
   179 
       
   180     (aNumber isMemberOf:SmallInteger) ifTrue:[
       
   181         ^ numerator > (denominator * aNumber)
       
   182     ].
       
   183     (aNumber isKindOf:Fraction) ifTrue:[
       
   184         ^ (numerator * aNumber denominator) > (denominator * aNumber numerator)
       
   185     ].
       
   186     ^ self retry:#> coercing:aNumber
       
   187 !
       
   188 
       
   189 < aNumber
       
   190     "return true if the receiver is less
       
   191      than aNumber, false otherwise."
       
   192 
       
   193     (aNumber isMemberOf:SmallInteger) ifTrue:[
       
   194         ^ numerator < (denominator * aNumber)
       
   195     ].
       
   196     (aNumber isKindOf:Fraction) ifTrue:[
       
   197         ^ (numerator * aNumber denominator) < (denominator * aNumber numerator)
       
   198     ].
       
   199     ^ aNumber lessFromFraction:self
       
   200 ! !
       
   201 
       
   202 !Fraction methodsFor:'testing'!
       
   203 
       
   204 negative
       
   205     "return true if the receiver is negative"
       
   206 
       
   207     (numerator < 0) ifTrue:[
       
   208         ^ (denominator < 0) not
       
   209     ].
       
   210     ^ (denominator < 0)
       
   211 ! !
       
   212 
       
   213 !Fraction methodsFor:'arithmetic'!
       
   214 
       
   215 + aNumber
       
   216     "return the sum of the receiver and the argument, aNumber"
       
   217 
       
   218     |n d|
       
   219 
       
   220     (aNumber isMemberOf:SmallInteger) ifTrue:[
       
   221         ^ (self class numerator:(numerator + (denominator * aNumber))
       
   222                     denominator:denominator) reduced
       
   223     ].
       
   224     (aNumber isKindOf:Fraction) ifTrue:[
       
   225         n := aNumber numerator.
       
   226         d := aNumber denominator.
       
   227 
       
   228         "save a multiplication if possible"
       
   229         denominator == d ifTrue:[
       
   230             ^ (self class numerator:(numerator + n) denominator:d) reduced
       
   231         ].
       
   232 
       
   233         ^ (self class numerator:((numerator * d) + (n * denominator))
       
   234                     denominator:(denominator * d)) reduced
       
   235     ].
       
   236     ^ aNumber sumFromFraction:self
       
   237 !
       
   238 
       
   239 - aNumber
       
   240     "return the difference of the receiver and the argument, aNumber"
       
   241 
       
   242     |n d|
       
   243 
       
   244     (aNumber isMemberOf:SmallInteger) ifTrue:[
       
   245         ^ (self class numerator:(numerator - (denominator * aNumber))
       
   246                     denominator:denominator) reduced
       
   247     ].
       
   248     (aNumber isKindOf:Fraction) ifTrue:[
       
   249         n := aNumber numerator.
       
   250         d := aNumber denominator.
       
   251 
       
   252         "save a multiplication if possible"
       
   253         denominator == d ifTrue:[
       
   254             ^ (self class numerator:(numerator - n) denominator:d) reduced
       
   255         ].
       
   256 
       
   257         ^ (self class numerator:((numerator * d) - (n * denominator)) 
       
   258                     denominator:(denominator * d)) reduced
       
   259     ].
       
   260     ^ aNumber differenceFromFraction:self
       
   261 !
       
   262 
       
   263 * aNumber
       
   264     "return the product of the receiver and the argument, aNumber"
       
   265 
       
   266     |n d|
       
   267 
       
   268     (aNumber isMemberOf:SmallInteger) ifTrue:[
       
   269         ^ (self class numerator:(numerator * aNumber)
       
   270                     denominator:denominator) reduced
       
   271     ].
       
   272     (aNumber isKindOf:Fraction) ifTrue:[
       
   273         n := numerator * aNumber numerator.
       
   274         d := denominator * aNumber denominator.
       
   275         ^ (self class numerator:n denominator:d) reduced
       
   276     ].
       
   277     ^ aNumber productFromFraction:self
       
   278 !
       
   279 
       
   280 / aNumber
       
   281     "return the quotient of the receiver and the argument, aNumber"
       
   282 
       
   283     |n d|
       
   284 
       
   285     (aNumber isKindOf:Fraction) ifTrue:[
       
   286         n := numerator * aNumber denominator.
       
   287         d := denominator * aNumber numerator.
       
   288         ^ (self class numerator:n denominator:d) reduced
       
   289     ].
       
   290     ^ aNumber quotientFromFraction:self
       
   291 !
       
   292 
       
   293 // aNumber
       
   294     "return the integer quotient of the receiver and the argument, aNumber"
       
   295 
       
   296     self negative ifTrue:[
       
   297          ^ ((numerator * aNumber denominator) // (denominator * aNumber numerator)) - 1
       
   298     ].
       
   299     ^ (numerator * aNumber denominator) // (denominator * aNumber numerator)
       
   300 !
       
   301 
       
   302 negated
       
   303     "optional - could use inherited method ..."
       
   304 
       
   305     ^ self class numerator:(numerator negated)
       
   306                denominator:denominator
       
   307 !
       
   308 
       
   309 reciprocal
       
   310     "optional - could use inherited method ..."
       
   311 
       
   312     numerator == 1 ifTrue:[^ denominator].
       
   313     ^ self class numerator:denominator
       
   314                denominator:numerator
       
   315 ! !
       
   316 
       
   317 !Fraction methodsFor:'truncation and rounding'!
       
   318 
       
   319 truncated
       
   320     "return the receiver truncated towards zero as Integer"
       
   321 
       
   322     ^ numerator // denominator
       
   323 !
       
   324 
       
   325 rounded
       
   326     "return the receiver rounded to the nearest integer as integer"
       
   327 
       
   328     self negative ifTrue:[
       
   329         ^ (self + (1/2)) truncated - 1
       
   330     ].
       
   331     ^ (self + (1/2)) truncated
       
   332 ! !
       
   333 
       
   334 !Fraction methodsFor:'double dispatching'!
       
   335 
       
   336 sumFromInteger:anInteger
       
   337     "sent when an integer does not know how to add the recevier, a fraction"
       
   338 
       
   339     ^ (self class numerator:(numerator + (anInteger * denominator))
       
   340                 denominator:denominator) reduced
       
   341 !
       
   342 
       
   343 differenceFromInteger:anInteger
       
   344     "sent when an integer does not know how to subtract the recevier, a fraction"
       
   345 
       
   346     ^ (self class numerator:((anInteger * denominator) - numerator)
       
   347                 denominator:denominator) reduced
       
   348 !
       
   349 
       
   350 productFromInteger:anInteger
       
   351     "sent when an integer does not know how to multiply the recevier, a fraction"
       
   352 
       
   353     ^ (self class numerator:(anInteger * numerator)
       
   354                 denominator:denominator) reduced
       
   355 !
       
   356 
       
   357 lessFromInteger:anInteger
       
   358     "sent when an integer does not know how to compare to the recevier, a fraction"
       
   359 
       
   360     ^ (denominator * anInteger) < numerator
       
   361 !
       
   362 
       
   363 sumFromFloat:aFloat
       
   364     "sent when a float does not know how to add the recevier, a fraction"
       
   365 
       
   366     ^ (aFloat * denominator + numerator) / denominator
       
   367 !
       
   368 
       
   369 differenceFromFloat:aFloat
       
   370     "sent when a float does not know how to subtract the recevier, a fraction"
       
   371 
       
   372     ^ (aFloat * denominator - numerator) / denominator
       
   373 !
       
   374 
       
   375 productFromFloat:aFloat
       
   376     "sent when a float does not know how to multiply the recevier, a fraction"
       
   377 
       
   378     ^ aFloat * numerator / denominator
       
   379 !
       
   380 
       
   381 quotientFromFloat:aFloat
       
   382     "sent when a float does not know how to divide by the recevier, a fraction"
       
   383 
       
   384     ^ (aFloat * denominator) / numerator
       
   385 ! !
       
   386 
       
   387 !Fraction methodsFor:'printing'!
       
   388 
       
   389 printString
       
   390     ^ '(' , numerator printString, '/' , denominator printString, ')'
       
   391 ! !