|
#16
|
|
|
|
|
On Feb 14, 8:08 am, "John Thingstad" <jpth> wrote:
> Pć Thu, 14 Feb 2008 13:50:18 +0100, skrev Greg Menke <guse>: >> Well the most straightforward way is Binary Coded Decimal (BCD). > One nibble (4 bits) is reserved for each digit 0-9. So you write a library > to access numbers this way. > (Many processors have support for this.) Writing such a library is a bit > cumbersome, but still easier than dealing with the imprecision explicitly > in bignums I would think. (Because humans think of precision in digits > not binary) What? Given exact rationals, you can implement the rounding rules arithmetically. You don't need to depend on how those numbers are implemented. E.g. suppose you are to round to the nearest 0.01 such that: 0.xy4... -> 0.xy 0.xy5 -> (if (evenp y) 0.xy (+ 0.xy 0.01)) 0.xy5... -> 0.xy + 0.01 You multiply the input by 100 to obtain xy.zw. To get the y digit, if necessary, truncate the number to integer, and compute the residue modulo 10. If the fractional part is less than half, take the truncated number and divide by 100. If it's greater than half, add 1 and divide by 100. If it's exactly half, apply the test to y. Here is some code, which has a few simplifying assumptions. One is that the input is rational. The second is that EXPT gives us a rational (and even if the exponent is negative). This works in CLISP but is nonportable. (defun round-even-odd-rule (input digits) (let* ((multiplier (expt 10 digits)) (sign (signum input)) (scaled (* (abs input) multiplier))) (multiple-value-bind (int frac) (truncate scaled) (* sign (/ (cond ((< frac 1/2) int) ((> frac 1/2) (1+ int)) (t (let ((leastdigit (mod int 10))) (if (evenp leastdigit) int (1+ int))))) multiplier))))) ;; round to integer: (round-even-odd-rule 1/2 0) -> 1 ;; round to multiple of 10: (round-even-odd-rule 1/2 1) -> 0 ;; round 1.125 to nearest hundredth: ;; should be 1.12 since 2 is even. (round-even-odd-rule 1125/1000 2) -> 28/25 ;; i.e. 112/100 or 1.12 ;; round 1.135 to nearest hundredth: ;; should be 1.14 since 3 is odd: (round-even-odd-rule 1135/1000 2) -> 57/50 ;; i.e. 114/100 ;; round 7885 to nearest thousand: (round-even-odd-rule 7885 -3) -> 8000 Of course, with BCD, to do the rounding, you just duplicate the input number, and then work on the digits directly. Converting BCD between internal representation and text is also trivial. (Have I, as I suspect, just summed up the complete gamut of the advantages of BCD?) |
|
|
|
#17
|
|
|
|
|
On Feb 10, 12:54 pm, Kent M Pitman <pit> wrote:
[..] > of pennies. And then write whatever methods on the class you wanted > to be able to do. +$, *$, etc. > > Even if there were a "fixed decimal" type or something like that, > you'd still have the issue of whether it was proper to do things like > multiply that times another fixed decimal. Using the DOLLARS class, > you could actually control it enough that it could add two DOLLARS > classes but forbid you to add a regular integer to that class, or that > could let you multiply DOLLARS times an integer, but not times > DOLLARS. Of course, if you use a rational to represent some currency amount exactly, and another rational to represent some multiplier exactly (e.g. 105/100 for 1.05 or 5% tax or whatever) then you can just multiply these two together exactly using the * operator, and then post-filter the result through a precise rounding rule. If you were doing pencil-and-paper arithmetic, you'd do the same: $123.95 ;; exact rational inputs x 1.05 -------- 6 1975 0 123 95 -------- 130.1475 ;; exact rational result Now apply specific rounding rule: e.g. round to nearest, with even-odd rule to resolve the equidistant case. 0.147 is closer to 0.15 than to 0.14, so: 130.15 ;; exact rational rounded result |
|
#18
|
|
|
|
|
Pć Thu, 14 Feb 2008 21:14:16 +0100, skrev Kaz Kylheku <kkylheku>:
> > What? Given exact rationals, you can implement the rounding rules > arithmetically. You don't need to depend on how those numbers are > implemented. > Of course not. > > ;; round 1.125 to nearest hundredth: > ;; should be 1.12 since 2 is even. > (round-even-odd-rule 1125/1000 2) -> 28/25 ;; i.e. 112/100 or 1.12 Fine but now you have to print it as 1.12 and don't mess up the precision.. > > ;; round 1.135 to nearest hundredth: > ;; should be 1.14 since 3 is odd: > (round-even-odd-rule 1135/1000 2) -> 57/50 ;; i.e. 114/100 > Again rational does the 'wrong' thing.. ie. it would have been just as easy to just keep it as 114/100 We haven't covered reading values from the user/file yet.. Doing it with BCD still seems easier to me. -------------- John Thingstad |
|
|
|
|
| Similar Threads | |
| monetary values Why do monetary values show up as the pound sign's? |
|
| How do I add a column of monetary numbers I have a column of amounts of money. Just want excel to add them up and give me a total. |
|
| Matching a name to a specified monetary amount I need to find the formula that can match a specified monetary value to a name. For instance if I type in A1 Name1 then in B1 $14.00 comes in or if I would have typed in... |
|
| Monetary Format Hi, Well, I'm developing one application that will have support for many languages and countries, in the application I need to show and to format the currency for the chosen... |
|
| Help on Monetary figures Someone must know but not me. Can i get my figure amounts to only display to 2d.p. while it is linked back to an access dbase? Thanks in advance |
|
|
All times are GMT. The time now is 12:17 AM. | Privacy Policy
|