From: Lloyd Zusman Date: 2004-10-31T17:12:02+09:00 Subject: Re: Rounding error ... [remainder of huge subject line truncated] "trans. (T. Onoma)" writes: > On Saturday 30 October 2004 04:31 pm, Lloyd Zusman wrote: > | For example, explain to me an algorithm which will "properly" do > | rounding in all of the following cases. How many decimal places will > | the result have, and will there or will there not be any rounding? > > You first will have to specify the problem set better then that. For > example by 2 & 3 I take it you are making a distinction between > integers and floats, or are we just dealing with reals here and > indifferent? If the former do you wish the to coerce ints to floats or > throw an error? Also what rounding? --You didn't specify any > percession, or what kind of draw option to use. OTOH, maybe you > believe these have to be rounded as is for the computer to store the > result. That's not so. I can represent the results of all these > calculations without rounding very easily. Let's specify all of the values to be floats in these examples. Of course the results of the calculations I specified can be easily represented in a number of textual formats. However, none of those calculations can be done in floating point without precision being lost and approximation being necessary. Perhaps you are thinking of eliminating floating point and having the computer use some other numerical representation ... like Rationals, perhaps ... ??? > | 1. 100 * 9.95 > | > | 2. 100 * (29.85 / 3) > | > | 3. (100 * 29.850) / 3.0 > | > | 6. 1 / 3 > | > | 7. 1 / 3.0 > | > | 8. 1 / sqrt(9) > | > | etc. etc. > | > | What is the intention of the programmer in each case, and what > | _should_ the answer be (in terms of number of decimal places, > | rounding behavior, truncation behavior, etc.). > > Did you read the alt thread? I'm not talking about variant viable > behaviors, depending on what one wants. I'm talking about what one > should be able to expect but doesn't get. I'll distill it for you, > try: > > (134.45 / (0.1)).round > (134.45 * (1.0/0.1)).round Yes, I did read the alt thread, and therefore, to avoid confusion, I'll stick with your example. Using floating point numbers, there is no way to guarantee that all pairs of calculations that fit the pattern in your example will yield the same results. Sorry, but that's just the nature of the beast. There is no floating point number that accurately represents 0.1. The best you can get is an approximation. The second expression is written to state that 1.0/0.1 is calculated _before_ the multiplication by 134.45. That's what the parentheses around that expression mean. This division yields a result that only approximates 10.0, and therefore, the result of the multiplication only approximates 1344.5 The only way this wouldn't happen would be for Ruby to evaluate the second expression like this: ((134.45 * 1.0) / 0.1).round But that's _different_ from what the original version of the statement says (don't forget that parentheses are _defined_ in Ruby and most other commonly used computer languages to specify the order of evaluation of statement components). Are you suggesting that Ruby should start ignoring the meaning of parentheses and to evaluate statements differently from how they are written? It seems like you are trying to introduce a "do what I mean, not what I say" aspect to Ruby. But how, in the general case, would Ruby know what someone "means", if it ignores the strict instructions that the programmer encodes via his/her use of parentheses and other language constructs? The goal you are trying for, if it's even possible, would have to be achieved with something other than floating point arithmetic, which by its very nature cannot guarantee that pairs of statements like the ones you specified above will give precisely equivalent results. Perhaps you should work on designing a new language that has following characteristics: 1. No floating point arithmetic is done by default; rather, all arithmetic involving values with decimal points is done with something like Rationals, BigDecimals, etc. (although note that rounding and truncation will still have to be done even in this case, and there will be cases where precision is lost in ways that are similar to the ones we've been discussing in this thread) Perhaps this hypothetical language would convert decimal numbers to rationals, as follows: (134.45 * (1.0/0.1)) becomes: ((134 + (45/100)) * (1 / (1/10))) This could be algebraicly reduced before anything is evaluated: ((134 + (45/100)) * (1 / (1/10))) => ((13400 + 45) * 10) / 100 => (13445 / 10) => (2689 / 2) => 1344 + 1/2 Of course, how would you algebraicly reduce this statement if the values of X, Y, and Z aren't known until run time? (X * (Y/Z)) 2. Parentheses around expressions are suggestions only and no longer specify strict evaluation order. For example, statement A might be transformed to statement B by the compiler: A. (134.45 * (1.0/0.1)) B. ((134.45 * 1.0) / 0.1) But what would you do in this case? (X * (Y/Z)) Should the order of evaluation be changed at run time, depending on the values of X, Y, and Z at the time that the statement is encountered? If so, what algorithm would you use for deciding when and how to change the evaluation order? 3. etc. -- Lloyd Zusman ljz@asfast.com God bless you.