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?

Last update: 2015.

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

 PDF Printing Version