February 07, 2004 Re: [bug?] Re: default float initialiser | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ilya Minkov | "Ilya Minkov" <minkov@cs.tum.edu> wrote in message news:c00gvg$1bt2$1@digitaldaemon.com... > Manfred Nowak wrote: > > Then please explain, why > > | real value; > > | printf("%d\n", cast(int) value); > > > > leads to the output > > | -2147483648 > > Should the cast maybe throw an exception here? Only in debug mode or always? Casting a nan to an int sets the "invalid" flag in the FPU. These flags are sticky; you can test for them using the C function fegetexcept(). |
February 07, 2004 Re: [bug?] Re: default float initialiser | ||||
---|---|---|---|---|
| ||||
Posted in reply to Manfred Nowak | In article <c02rb2$2ps5$1@digitaldaemon.com>, Manfred Nowak says... > >On Sat, 07 Feb 2004 08:16:34 +0000, Georg Wrede wrote: > >[...] >> No, it should not. The point of cast is to have the calling function _consider_ the bit pattern as what the cast states. >[...] > >Please check your statements before posting or do not post at all. > >Setting a real variable to for example `3.141516' and then casting it to int outputs `3'. I have checked the bit pattern of the real variable there is no bit pattern for an int 3 in it. Thanks for the prompt correction! It's good somebody is awake at the keyboard, before too many newbies learn the wrong thing. I musta had a serious blackout! :-/ |
February 16, 2004 Re: default float initialiser | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | > > "Matthew" <matthew.hat@stlsoft.dot.org> wrote in message news:bvo60s$2nur$1@digitaldaemon.com... > > > > NaN seems arbitrarily inconsistent. > > > > > > That's only because there is no NaN value for integers. > > > > Sure, but if consistency is what you're after, why choose 0 for integers? > > Why not -1? > > Consistency is not possible because there is no NaN value for integers. So we just do the best we can. > > > > > Using 0 for integers merely leads us to the current mindset whereby the expectation is the all variables are initialised to their "zero value", rather than their "null value". > > > > > null is the NaN > > > value for pointers and references, and that is used, too. > > > > Here's the way it looks to me: > > > > 1. Pointers/references > > do not have a "zero value" > > "null value" is null > > > > 2. Integers > > "zero value" is 0 > > "null value" is 0 > > > > 3. Floating point > > "zero value" is 0 (or 0.0, if you like) > > "null value" is NaN > > > > Since pointers/references do not have a "zero value", but their "null > value" > > is what one would choose to be if "zero value" had meaning to pointers/references, I think there's a strong argument that floating > point's > > should be default initialised to their "zero value" rather than their > "null > > value" simply because that is what everyone will expect. > > > > > Even better would > > > be if the CPU offered some way to tag a location as 'empty', but so far, > > > this does not exist outside of the 8087 registers. > > > > > > I completely agree, and if integers had a well-known "null value" then > this > > argument would be moot. > > > > Indeed, maybe we should decide that top-bit-set is the null value, e.g. -128, -32768, etc ? I know this sounds silly, but it is consistent > with > > NaN. The reason it sounds silly is that we all know that 0 is the "null value" of integers. Alas, this knowing is what causes us all to believe > that > > 0.0 is the "null value" of floating points, which I grant you it's not. > > > > > > > > > I agree that one will much more often want to rely on it being 0 than > > NaN. > > > > > > The point is to provide a useless value so 'uninitialized' variable > > problems > > > will be exposed, and a consistent value to aid in tracking the problem > > down. > > > > > > > Is the rationale for NaN documented anywhere? I'd like to read it. > > > > > > The idea is if you want to use it, you should set it to a value first. > The > > > NaN is to catch paths where you used it but failed to initialize it. > > > > I understand that this is the intention, but since integers do not have a > > "null value", and integer programming is far more common that floating point, people will come to believe that all variables are > zero-initialised, > > rather than null-initialised. I think this will cause more problems than > it > > is intended to solve. > > I understand your point, but I don't agree. There is really no missing a NaN > value in one's output. But it's EASY to miss a spurious 0 or the effect of a > spurious 0 on the output. You can apply this argument on integers as well which are initialized with 0. > > > Since everyone will always "know" that > > zero-initialisation is happening, the issue of whether one might forget to > > initialise it is moot: therefore there's no need for NaN. > > I don't agree that forgetting to initialize something is the same thing as relying on it being initialized to 0. All I'm trying to accomplish here is helping people remember to think about what they need a floating point value's initial value to be. If you want to remind people then issue an warning. That is explicit and will be seen by everyone. Relying on a weird output does not apply to all problems that a general purpose language is used for. Imagine a 3D Engine: You do not see the values of the floats - you just see triangles. So bugs like that are not easy to catch. > > > And wouldn't it just be better for the compiler to tell you at > compile-time > > that you've not initialised something, > > It would be, except that it is not possible for the compiler to unambiguously determine that a variable is not initialized. This leads to putting in 'dummy' initializations to shut up the compiler, and the maintenance programmer is left to wondering why x is being set to a value that is never used. > > > rather than you having potentially > > huge amounts of effort in tracing/debugging back to find that a variable > > started life as NaN instead of 0.0 ? > > I'd be shocked if it was a huge effort. In fact, by the nature of how NaN's > work, it should be much easier to trace back than a spurious 0. Also, 0's can affect your output in subtle ways and therefore go unnoticed. There is no unnoticing of a NaN output. If your intention is to write robust floating > point code, NaN is the one to pick for unintended initializations. > I think initializing floats variables with NaN can lead to the same problem you are fighting against: dummy initialization. It might turn out that most people will just initialize all their floats with 0.0, just to have a good starting point. So it seems like both approaches NaN and compiler warnings can lead to dummy initialization, depending on what people develop. So why not initialize to 0? Generally speaking, floats and integers are almost the same. You can add them, you subtract them, divide and so on. They are just numbers. Consider templates: Make a templated class using numbers. Instanciate the template with integers and with floats. Both instances use numbers in general. But the integers are initialized with 0 and the floats with NaN! That is not really straight forward, especially if people don't know what NaNs are. They are wondering what the heck is that? The concept of NaNs is specific to certain applications of floats. I think usually NaNs don't occur. So why do you want to introduce NaN to applications that would never have to deal with them? BTW, what is the result of "1 divided by NaN" on Win95/98 in D? Personally, I think what people helps not to make mistakes are simple concepts. An easy concepts are: all variables are initialized with garbage. all variables are initialized with 0. The following concept is not easy: All variables are initalized with the "null-value". Null values of references are "null". Null values of integers are 0. Null values of floats are NaN. Furthmore, if you consider the background of most people that have programming expierence. They come from languages where floats are initialized with 0 by default or with garbage. So what do you think they will assume about the default value of floats when they figured out that integers are initialized with 0 and references with null? NaN? I don't think so. Is there any language that initializes floats with NaN? All the languages I know just don't initialize or do it with 0, that is another reason for newbies to assume a float default value of 0. 0 is such a nice number! How often do I write in constructors memset(this,0,sizeof(*this)); .... Cheers, Jan-Eric |
February 16, 2004 Re: [bug?] Re: default float initialiser | ||||
---|---|---|---|---|
| ||||
Posted in reply to Georg Wrede | I think fortran behave in the way that you described. ;)
--
Jan-Eric Duden
"Georg Wrede" <Georg_member@pathlink.com> wrote in message
news:c03nkk$17eq$1@digitaldaemon.com...
> In article <c02rb2$2ps5$1@digitaldaemon.com>, Manfred Nowak says...
> >
> >On Sat, 07 Feb 2004 08:16:34 +0000, Georg Wrede wrote:
> >
> >[...]
> >> No, it should not. The point of cast is to have the calling function _consider_ the bit pattern as what the cast states.
> >[...]
> >
> >Please check your statements before posting or do not post at all.
> >
> >Setting a real variable to for example `3.141516' and then casting it to int outputs `3'. I have checked the bit pattern of the real variable
there
> >is no bit pattern for an int 3 in it.
>
> Thanks for the prompt correction! It's good somebody is awake at the keyboard, before too many newbies learn the wrong thing.
>
> I musta had a serious blackout! :-/
>
>
|
February 17, 2004 Re: default float initialiser | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jan-Eric Duden | Jan-Eric Duden wrote: > If you want to remind people then issue an warning. > That is explicit and will be seen by everyone. > Relying on a weird output does not apply to all problems that a general > purpose language is used for. > Imagine a 3D Engine: You do not see the values of the floats - you just see > triangles. So bugs like that are not easy to catch. That's what Design By Contract is intended for. Whenever you use a NaN in an expression, result is also NaN. Thus it is enough to insert a contract on the very final stage of the engine to ensure that the complete engine is bug-free. If there are any, this means the program is buggy and more earlier contracts have to be inserted to track it down. I think also any operation with NaN sets the error flag, which could automatcally be checked at all return points of a function and exception raised. This would easily show where the problem first comes to light. Of course, there must be a well-defined way to clear the error flag. > I think initializing floats variables with NaN can lead to the same problem > you are fighting against: dummy initialization. > It might turn out that most people will just initialize all their floats > with 0.0, just to have a good starting point. > So it seems like both approaches NaN and compiler warnings can lead to dummy > initialization, depending on what people > develop. So why not initialize to 0? One cannot be everyone's doctor. People are usually educated from C++ and Java use that floats (just as anything else) should be initialised with a sane value, just before use. 0.0 is not too often what you want with floats, and if you do you just know to remember it. However, in C++ values are initailised with bit noise. This means that if you by some occasion put initialisation at some point which gets skipped (whoops!) or forget to initialise in a certain code path (whoops!) then you get a bit pattern. You can track it itself with a debugger, however you cannot get automatically warned, since the number that it represents is actually fully legal - because the same pattern had to be for everything. And after a few operations you don't have a problem indication, just silly plain false results. And it's just not any different with 0. But with NaN you have NaN in a final result which is easy to ensure that it does not happen. And like, you don't have a global SillyArray, and initialise every pointer to point into it when you don't know any better value? You initialise it with null! So that the program would crash when using it, thus indicating a failure. > Generally speaking, floats and integers are almost the same. You can add > them, you subtract them, divide and so on. > They are just numbers. Floats by definition have significant problems that every programmer should be aware of. Besides, floats are usually numeric values, and integers are usually simply counters. So i don't buy that argument. > Consider templates: Make a templated class using numbers. Instanciate the > template with integers and with floats. > Both instances use numbers in general. But the integers are initialized with > 0 and the floats with NaN! Templates are written by library writers, professionals. If a template is not numeric, then the initailization doesn't actually matter since it is transparent. If a template is numeric and requieres a specific start value for calculations, it is up to template designer to ensure that it gets initailised correctly. If it is up to user to initialise the values - again, NaN allows to dagnosticise a problem at some point. > That is not really straight forward, especially if people don't know what > NaNs are. > They are wondering what the heck is that? > The concept of NaNs is specific to certain applications of floats. > I think usually NaNs don't occur. > So why do you want to introduce NaN to applications that would never have to > deal with them? This is good that NaNs usually don't occur - relying on NaNs in an application would make them unusable for debugging. And theother way around, numeric code relying on NaNs to *work* would be an unworkable nonsense. There was a big argument on what to do when an illegal operation is beling made. Obviously, you can recall what happens if you integer divide by zero? The dreaded CPU Exception 200, which terminates the application. This was clearly unacceptable for numeric work, and so a special value was reserved to indicate errors for late checks or due to illegal input. So why not use it? Besides, what's the language manual for? Of course it should contain explaination what NaNs are and why. You don't just go off and program in a language you don't know without having read the manual, do you? Don't consider the current spec a manual, it has yet a long way to go and is intended for people who know what this&that is or can look up elsewhere on their own. > Personally, I think what people helps not to make mistakes are simple > concepts. > An easy concepts are: > all variables are initialized with garbage. Very, very evil. > all variables are initialized with 0. This may be not bad, but then again it's not nearly as helpful as NaN. > The following concept is not easy: > All variables are initalized with the "null-value". Null values of > references are "null". Null values of integers are 0. Null values of floats > are NaN. It's the most practical one. Don't consider programmers stupid! And if it does get in the way, then in a fairly easy to diagnosticize way. > Furthmore, if you consider the background of most people that have > programming expierence. > They come from languages where floats are initialized with 0 by default or > with garbage. So what do you think they will assume about the default value > of floats when they figured out that integers are initialized with 0 and > references with null? NaN? I don't think so. Then let them program as if it were garbage even, it won't make it any worse than they would now. Again: what practical improvement would you see from zero init or from real garbage init? > Is there any language that initializes floats with NaN? > All the languages I know just don't initialize or do it with 0, that is > another reason for newbies to assume a float default value of 0. Don't be so narrow-minded. I think someone can come up with one. Besides, i ask you, is garbage any better than NaN? C & C++ DoItWithGarbage(tm) :> Besides, if we do everything like the others, where would the progress be? D has been blamed for being not innovative enogh, but i argue that this subtle point with NaN init is one of the key innovations in D. > 0 is such a nice number! How often do I write in constructors > memset(this,0,sizeof(*this)); .... Uh-oh! That's what programmers had to spend ther time with before D came. ;> Besides, memset to 0 doesn't guarantee much useful, besides that integers are initialised to 0. Floating-point and pointers may have (in principle) 0 or null represented in a different bit-pattern! Though this may have worked on our machines for years... -eye |
Copyright © 1999-2021 by the D Language Foundation