Precision of Floating-Point Data Types - Test

This section describes testing results of precision comparison on floating-point data types: 'float', 'double', and 'decimal'

If you run the tutorial example presented in the previous section, you will get this output:

Testing 1/3:
 f = 0.3333333
 d = 0.333333333333333
 m = 0.3333333333333333333333333333
 f*3 = 1
 d*3 = 1
 m*3 = 0.9999999999999999999999999999
 (double)f*3 = 1.00000002980232
 (decimal)f*3 = 0.9999999
 (decimal)d*3 = 0.999999999999999
 (double)((float)i/3)*3 = 1
Testing 2/3:
 f = 0.6666667
 d = 0.666666666666667
 m = 0.6666666666666666666666666667
 f*3 = 2
 d*3 = 2
 m*3 = 2.0000000000000000000000000001
 (double)f*3 = 2.00000005960464
 (decimal)f*3 = 2.0000001
 (decimal)d*3 = 2.000000000000001
 (double)((float)i/3)*3 = 2

Question 1: Why ((float)1/3)*3 = 1?

Don't try to answer it with the possibility that the compiler is smart, and optimizes (/3)*3 as *1. I have tried to get the /3 part from a variable like as shown in this example program, from a method, or even from another class that compiled separately. They all give me the same result.

I believe that the answer is related to the storage algorithm of floating-point data types. But I don't have time to figure it out yet.

Question 2: If ((float)1/3)*3 = 1, then why ((decimal)1/3)*3 = 0.9999999999999999999999999999?

I also don't have a clear answer yet. But I believe that the answer is also related to the storage algorithm of floating-point data types.

No matter what the answer is, this behavior is telling us that "decimal" is not a natural extension of "float", like "double" extending "float".

If you are a designer, don't ask your developers to change "double" to "decimal" immediately. Do some experiments first.

Question 3: If ((float)1/3)*3 = 1, and ((decimal)1/3)*3 < 1, then is the float type more accurate that the decimal type?

I will leave this question to you to answer.

Question 4: If f is (float)1/3 = 0.3333333, then why (double)f*3 = 1.00000002980232?

I am expecting (double)f*3 = 0.9999999, because casting f into "double" will force the expression to be evaluated in double precision, giving 0.9999999. What do you think?

Question 5: If (double)f*3 = 1.00000002980232, why (double)((float)1/3)*3 = 1?

The difference here is that (float)1/3 is evaluated first and stored in a variable f.

My guess to what happened here is that all floating data expressions are evaluated in double precision. What do you think?

Table of Contents

 About This Book

 Introduction of C# (C Sharp)

 Data Type and Variables

 Logical Expressions and Conditional Statements

 Arrays and Loop Statements

 Data Type Features

Floating-Point Data Types

 Precision of Floating-Point Data Types

Precision of Floating-Point Data Types - Test

 Performance of Floating-Point Data Types

 Performance of Floating-Point Data Types - Test

 IEEE 754 Standards - "float" and "double"

 IEEE 754 Standards - "float" and "double" - Test

 Binary Representation of "decimal"

 Accuracy of "decimal" Data Type

 Passing Parameters to Methods

 Execution Environment Class

 Visual C# 2010 Express Edition

 Class Features

 C# Compiler and Intermediate Language

 Compiling C# Source Code Files

 MSBuild - Microsoft Build Engine

 Memory Usages of Processes

 Multithreading in C#

 Async Feature from C# 5

 System.IO.FileInfo Class

 System.Diagnostics.FileVersionInfo Class

 WPF - Windows Presentation Foundation

 Partial Classes and Partial Methods

 Outdated Tutorials

 References

 Full Version in PDF/ePUB