|
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 ! ! |