Here's an interesting observation:
Start with the mathematical value 0.9
Convert that to a binary number. For the same reason that 1/3 cannot be expressed in a finite number of digits in base 10, the number 0.9 cannot be expressed in a finite number of digits in base 2. The exact mathematical value is:
0.1 1100 1100 1100 1100 1100 1100 1100 ... with the "1100" repeating forever.
Let's store this value in an IEEE-754 single-precision floating-point value. (In SQL Server, this is called REAL type). To do that we have to round to 23 significant bits. The result is:
0.1 1100 1100 1100 1100 1100 11
Convert this to its exact decimal equivalent, you get this:
0.89999997615814208984375
Round that to 16 places after the decimal point. You get:
0.8999999761581421
Which is coincidentally the value you show as your example.
If you do the same thing to 3.1, you get 3.0999999046325684
Is it possible that all your inputs are simply numbers with one digit after the decimal point, which have been stored as a floating-point value, and then converted back into decimal?
decimal<>float. By "I have decimal data" do you really mean "I have float data"? If not, is your data actually adecimaland not afloat? Either way, never use avarcharto store numerical data.FLOATor go withDECIMAL, never use a string type to store numerical data, regardless of storage considerations. The only time that might be appropriate is if you have a very specific need to store data received from an external system exactly as you got it, character for character, even if it also has a numeric value. This is clearly not one of those cases. If storage was even a concern at all, you should consider things like row and page compression before the data type, simply because mixing up strings and numbers is such a huge source of pain.