Jon Skeet said:
Compare that with the quote quoted above (if you see what I mean).
It seems that in the case of INTEGER and DECIMAL, "the range of valid
values" is deemed to be "those which can be stored exactly" whereas for
FLOAT Mike deems it to be "anything between the minimum value and the
maximum value".
When I spoke of the "range" of valid values, I should have used the more
proper term "set" of valid values, and I did correct that. My bad. Of
course I never claimed FLOAT was "inaccurate", as you indicated in a prior
post; so I guess we all make the occasional typo.
Riddle me this, Skeetman: When I store the FLOAT value 28.08 in SQL Server
2000 and SELECT it in Query Analyzer it returns 28.079999999999998. When I
retrieve the same value in .NET from the same table in SQL Server, it
returns what the OP discovered: 28.080000000000002. You indicated that
when assigning a floating point value of 28.08 to a variable on the .NET
side that you received a different number. My question to you is plain and
simple: Which one is the "exact" representation of 28.08? The fact that
three different methods using the IEEE standard format can interpret the
same data three different ways (and all Microsoft products by the way) makes
a pretty convincing argument for calling the IEEE format "approximate".
Either 28.08 shouldn't be regarded as being "in the range of valid
values" for FLOAT, *or* it should be regarded as being "in the range of
valid values" for DECIMAL(1,2). I'm happy to use either definition, so
long as it's used consistently.
If you feel like compiling and publishing a complete list of valid values
for the FLOAT and REAL types, I will be happy to concede this point. I
agree that FLOAT and REAL do have a set of valid values and a set of invalid
values. However, considering the precision and scale allowed with FLOAT and
REAL, and the upper and lower bounds involved, plus the fact that every
client seems to interpret the same FLOAT and REAL data differently, I
imagine it's going to be quite a chore. With the INT type, there is a
well-defined set of valid values: All of the integer values
between -2147483648 and 2147483647, inclusive. DECIMAL (1,2) isn't even a
valid construct. You can't have one total digit and two digits after the
decimal point. You can, however, have DECIMAL (3, 2) which would include
all of the values between -9.99 and +9.99 consisting of three total digits
and two digits after the decimal point. And that's the same no matter what
client you are using.
I'll be more than happy to start calling "FLOAT" and "REAL" exact data types
when you create and publish that complete list of the set of valid values
for FLOAT and REAL. I would suggest starting with the valid values as .NET
interprets them, and the second part of your treatise can include the valid
values as Enterprise Manager interprets them. The next section could cover
SQL 2005, and then it would be handy to have the list of valid values as
interpreted by SQL 2005's XQuery implementation (which I've confirmed is at
least slightly different from the SQL Server version - somewhere around the
36th digit after the decimal point or so).
If you apply the definition of "range of valid values" Mike has used
for FLOAT to INTEGER/DECIMAL, you would have to concede that they are
not exact: 1/3 is between the min and max values of DECIMAL(1,2) but is
not exactly representable, for example.
As I said, "set of valid values". If you care to provide the "set of valid
values" for FLOAT/REAL, I'll be happy to concede that point.
And by the way, your 1/3 operation is first rounded off/truncated to an
inexact value by the division operator; not by the assignment to
INTEGER/DECIMAL. During assignment it is rounded again; but it was already
made an inexact decimal value (or at least 1/3.0 would be; 1/3 would be
zero) by the division operator, so there is no reason to think that
assignment of an inexact decimal value to an INTEGER/DECIMAL value could be
made more exact by the simple act of assignment. Unless you feel otherwise?
In reverse, if you apply the definition of "range of valid values" Mike
has used for INTEGER/DECIMAL to FLOAT, then your claim that "not all
members in the range of valid values can be stored in an exact
representation" is clearly incorrect (by definition).
What happens if you apply the "set of valid values" that I used for
DECIMAL/NUMERIC? As I said, publish the complete set of valid values for
FLOAT/REAL as interpreted by the various platforms that use them, and I'll
happily concede that point to you.
I suspect that any definition which can be applied *consistently* to
INTEGER, DECIMAL and FLOAT but which deems FLOAT to be "approximate"
and INTEGER/DECIMAL to be "exact" by examining the "range of values"
has to specifically refer to base 10 representations of numbers. Of
course, I'd be happy to be disproved - Mike, care to construct such a
definition?
Sure, how about this: "Exact data types are those data types which can
store and retrieve single values coincident with their type without loss of
data, and without the introduction of error."
What was your definition again? Was it something like "if it can be stored
in 1's and 0's it's exact - regardless if what i put in is the same as what
i got back?"