<snip>
I'm replying to the original post as this is going to be a summary
post. I've started repeating myself, and I'm sure I'm not the only one.
I don't see any sign that anyone's convincing anyone of anything, and
as I effectively started this mess, I think it makes sense for me to be
the one to end it (if others want it ended). At least, I expect when I
stop posting the thread will probably die fairly soon - if it doesn't,
of course, that's fine. My previous attempt to leave the thread clearly
failed miserably so this time I've set my newsreader to ignore the
thread. In a week I'll "unignore" it to read any extra responses, but
by then I'm sure my sense of netiquette will overwhelm my desire to
respond
In the unlikely case that anyone *really* wants to hear any
more from me, please mail me.
So, I thought I'd just summarise my position for the sake of anyone
who's interested in the future. Here we go:
1) I believe the correct answer to the OP's question of why 28.08 shows
up as 28.08000(etc)2 is that the conversion from a decimal number to a
binary number (e.g. a float) is one which can lose information. The
result of the conversion is stored exactly, but that result isn't the
same as the original number.
2) I agree with everyone else in terms of what the OP should do: use a
decimal based type.
3) I suspect we all at least mostly agree on the actual technical
aspects of what's happening, but we come from very different points of
view. My point of view tries to be "base-agnostic", viewing a number as
a number regardless of base, whereas the point of view which treats
float as "approximate" places a greater importance on decimal numbers
than other numbers.
4) I believe that the float type can accurately store and retrieve
every value it can accurately represent. This set of values is *not*
every number within the range of the minimum to the maximum values of
the type, just as integer types can't represent every number between
their minimum and maximum values - they can only represent every
*integer* between those values.
5) I believe that the business of which base literals are usually
expressed in is irrelevant to whether or not the values that a type
stores are exact or not. There will always be a conversion involved
from a decimal type to a binary type, and that conversion will always
be "lossy". I believe people should be aware of that, as well as being
aware that the value actually stored is an exact value - just not
necessarily the value they would expect. I also believe it's pretty
much as easy to explain that as to just say that float is an
approximate type. Of course, it's definitely worth pointing out that if
you want a conversion from a decimal literal which is lossless (within
the appropriate range/scale/precision) you should use a decimal type.
6) I agree that the examples I've given about base 3 values are
irrelevant to what will actually happen in real life, but I believe
they lead to a useful thought experiment which shows that float is just
as "exact" as decimal. Every type we've been talking about (float,
integer, decimal) has a set of values it can represent, and when
presented with a value from a type which can represent values not in
the set, the original value may not be representable. (It's not
*necessarily* an information-losing conversion - converting from uint
to int and back in C#, for instance, you can avoid losing data but you
can't always represent the original value.)
I dare say I've missed some points I've made throughout the rest of the
discussion, but never mind. I hope others have found the discussion as
interesting as I have.