Compiler warnings are not intended for those who haven't had adequate instruction. They're intended for cases when those with adequate instruction make potential mistakes.Uri Blass wrote:I disagree.xsadar wrote:Your compiler doesn't give you a warning when you write d = 0.01, because (1) when you use a feature it's expected that you already know how it works, and (2) it would have to give you an approximation warning (very nearly) every time you use a floating-point literal, which would be annoying to those who actually understand and need to use floating point arithmetic, not to mention that it would hide legitimate warnings.Uri Blass wrote:I get almost the sameZach Wegner wrote:Doubles can represent integers exactly, but that's not what we're doing. We're trying to represent fixed-point decimals of the form x.yy. You cannot represent 1/100 exactly in a double, as you must round at some point:Uri Blass wrote:I agree about point 1 but I disagree about 2.
You can represent every integer as double.
You even can have exactly the same evaluation when you replace integer by double and the only difference is that you are going to be slower.And though there is a one-to-one correspondence between every centipawn evaluation to its double representation, the rounding will crop up. Notice how 1/100 is rounded so that the double representation is bigger than 1/100? Try running this program:Code: Select all
0.0100000000000000002081668171172168513294309377670288085937500000000000000000000000000000000000000000
You would expect s to be either exactly 10, or maybe a bit bigger? Here's what it actually is:Code: Select all
#include <stdio.h> main(void){ double d = 0.01, s = 0; int i; for (i = 0; i < 1000; i++) s += d; printf("%.100f\n", s); }
Which is _less_ than 10.Code: Select all
9.9999999999998312461002569762058556079864501953125000000000000000000000000000000000000000000000000000
Now if you wanted to use "binary" values, and have your base unit be 1/256 or whatever of a pawn, go ahead. Or you could also use doubles with each number scaled up by 100 or so, but then what's the point?
I get
9.9999999999998312000000000000000000000000000000000000000000000000000000000000000000000000000000000000
I understand that 0.01 is binary approximation of 0.01 and it seems that the C is misleading.
I think that they simply should not allow me to write d=0.01 without warning by the compiler that d is not 0.01 but binary approximation of that value and double means
the finite set of non-zero values of the form s * m * 2e, where s is 1 or -1, and 0 < m < 253 and -1075 <= e <= 970.
.
I wonder why they do not do it.
I even could not see it based on clicking help on the word double and I had to search in google to find the following link that gives me the exact range of data
http://www.dotgnu.org/pnetlib-doc/System/Double.html
When I only click on help about double and later about data type range
I got simply that range of values of double is
1.7E +/- 308 (15 digits)
Clearly misleading.
Uri
However, it does appear that your documentation could have been a bit better. I'll have to admit though that I'm quite surprised that you didn't know floating-point values were binary approximations. I even thought it was implied in your response to Bob when I first read it.
The compiler should allow the user to disable some type of warning but
I think that it should warn the user about something that is not correct.
Not everybody studied computer programming at university and know it and at least people who learn C by other ways may not know it.
It is obvious that the computer cannot calculate correctly every division because of finite memory but it is not obvious that the computer cannot calculate correctly numbers like 0.01 that are constants.
It is simply counter intuitive and if I want to have numbers in base 2 and I compose computer language then my first thought is simply not to allow expressions like 0.01 and I can allow instead of it
only numbers in base 2 or base 4 or base 8 or base 16.
Second thought is that maybe I want to allow 0.01 for people who prefer to use base 10 and do not care about the error
but if people want to use base that is not a power of 2 and if they do not disable warning they should get a warning by the compiler.
Note that in case that the compiler does not allow 0.1 but allow 1/10 I could probably guess without more hints that 1/10 is not an exact value for the same reason that I know that 1/3 is not an exact value.
Uri
But, if we were to have a compiler warning, perhaps just a warning to not use floating point variables unless you know what you're getting yourself into. Not representing decimal and other fractions exactly is only one of the potential problems. Many of the rules of math don't work as you expect. As others have mentioned, with floating-point arithmetic ((a + b) + c) is not equivalent to (a + (b + c)). I've taken entire courses on the subject, and I prefer to stay away from using floating point values unless it's absolutely necessary.
Regarding writing floating-point constants in other bases so you have exact values, floating-point was not intended for representing exact values. If you want exact values you use integers (which was Bob's original point). And I see no reason why you would ever want to write typical floating-point constants (like Pi, or the speed of light, or the mass of an object) in another base.