Click here to Skip to main content
14,391,232 members

Float Point Numbers as Approximates & Using Errors

Rate this:
4.79 (13 votes)
Please Sign up or sign in to vote.
4.79 (13 votes)
1 Apr 2017CPOL
Floating point numbers as approximates and understanding error happened when using single and double data types

CFloat.vb is a class to handle and explain float point numbers in VB.

What are Floating-point Numbers

In computing, floating point is approximates. Floating point numbers are stored in binary format and converting from decimal number will return not the exact decimal number, but the nearest number to it that float point number can expose, as example: calculating 0.43 + 0.000001 - 0.430001, in C#, VB, VBA, Python, PHP, Java will not return 0!!

Storage Diagram

Single is stored in 4 bytes = 32 bits as the following binary storage diagram. S is signal bit, E is Exponents bit & F is fraction bit.
Fraction is called mantissa too.

Binary format of Single precision number is as follows:

Please note that the patterns may have some little differ from one compiler to other

S EEEE EEEE FFF FFFF FFFF FFFF FFFF FFFF

  Memory
Hexadecimal
Signal
Bit
Exponent
Hexadecimal
Fraction
Hexadecimal
Epsilon
Smallest positive number
1.4E-45
0000 0001 0 00 000 0001
Zero; +0! 0000 0000 0 00 000 0000
Negative Zero; -0! 8000 0000 1 00 000 0000
1! 3F80 0000 0 7F 000 0000
The smallest number > 1
1.00000012!
3F80 0001 0 7F 000 0001
Not a number; NaN FFC0 0000 1 FF 400 0000
Infinity; ∞ 0F80 0000 0 FF 000 0000
Negative Infinity; -∞ FF80 0000 1 FF 000 0000

Binary format of Double precision number is as given below:

S EEEE EEEE EEE FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF

  Memory
Hexadecimal
Signal
Bit
Exponent
Hexadecimal
Fraction
Hexadecimal
Epsilon
Smallest positive number
5E-324
0000 0000 0000 0001 0 000 0 0000 0000 0001
Zero; +0# 0000 0000 0000 0000 0 000 0 0000 0000 0000
Negative Zero; -0# 8000 0000 0000 0000 1 000 0 0000 0000 0000
1# 3FF0 0000 0000 0000 0 3FF 0 0000 0000 0000
The smallest number > 1
1.0000000000000002#
3FF0 0000 0000 0001 0 3FF 0 0000 0000 0001
Not a number; NaN FFF8 0000 0000 0000 1 7FF 8 0000 0000 0000
Infinity; ∞ FF00 0000 0000 0000 0 7FF 0 0000 0000 0000
Negative Infinity; -∞ FFF0 0000 0000 0000 1 7FF 0 0000 0000 0000

Unexpected Code Run Caused by Floating Point

Since floating point is approximates, then adding and mathematical operation does not always lead to the exact result.

Addition test:

//C#
public void TestAdd()
{
    double V = 0;
    V = 0.43 + 1E-06 - 0.430001;
    if (V != 0) {
	    Interaction.MsgBox("It will go here!");
    }
    float f = 0;
    f = 0.43f + 1E-06f - 0.430001f;
    if (f != 0) {
	    Interaction.MsgBox("It will go here!");
    }
}
'VB
Sub TestAdd()
    Dim V As Double
    V = 0.43# + 0.000001# - 0.430001#
    If V <> 0 Then
        MsgBox("It will go here!")
    End If
    Dim f As Single
    f = 0.43! + 0.000001! - 0.430001!
    If f <> 0 Then
        MsgBox("It will go here!")
    End If
End Sub

Special values:

'VB
Sub Test(x As Double)
    If x > 0 Then
        MsgBox("X > 0")
    ElseIf x = 0 Then
        MsgBox("X = 0")
    ElseIf x < 0 Then
        MsgBox("X < 0")
    Else
        MsgBox("This is a possible case! What is the value of X hear?")
        Dim R =
        (Double.NaN = 0) = False AndAlso
        (Double.NaN < 0) = False AndAlso
        (Double.NaN > 0) = False
    End If
End Sub

Sub Test(x As Single)
    If x > 0 Then
        MsgBox("X > 0")
    ElseIf x = 0 Then
        MsgBox("X = 0")
    ElseIf x < 0 Then
        MsgBox("X < 0")
    Else
        MsgBox("This is a possible case! What is the value of X hear?")
        Dim R =
        (Single.NaN = 0) = False AndAlso
        (Single.NaN < 0) = False AndAlso
        (Single.NaN > 0) = False
    End If
End Sub
//C#
public void Test(double x)
{
	if (x > 0) {
		Interaction.MsgBox("X > 0");
	} else if (x == 0) {
		Interaction.MsgBox("X = 0");
	} else if (x < 0) {
		Interaction.MsgBox("X < 0");
	} else {
		Interaction.MsgBox("This is a possible case! What is the value of X hear?");
		dynamic R = (double.NaN == 0) == false && (double.NaN < 0) == false && 
        (double.NaN > 0) == false;
	}
}

public void Test(float x)
{
	if (x > 0) {
		Interaction.MsgBox("X > 0");
	} else if (x == 0) {
		Interaction.MsgBox("X = 0");
	} else if (x < 0) {
		Interaction.MsgBox("X < 0");
	} else {
		Interaction.MsgBox("This is a possible case! What is the value of X hear?");
		dynamic R = (float.NaN == 0) == false && 
		(float.NaN < 0) == false && (float.NaN > 0) == false;
	}
}    

How to Get Float Point Value from its Exponent and Fraction

The following function will get the double value of a float point number. The Exponent Bias and Fraction Base of the float point number is dependant on the type of floating point. See the table.

Type Total Bits Exponent bias Fraction base
Half 16 15 2^10
Single 32 127 2^23
Double 64 1023 2^52
Extended 82 16383 2^64
Quad 128 16383 2^112

The value of number is calculated from the formula:

Exponent <> 0:

Value = ±2^(Exponent - ExponentBias) * (1 + Fraction / FractionBase)

Exponent = 0:

Value = ±2^(1- ExponentBias) * ( Fraction / FractionBase)

'VB
Function GetDoubleValue(IsNegative As Boolean, Exponent As UInt16,
        Fraction As UInt64, ExponentBias As UInt16, FractionBase As UInt64) As Double
    If Exponent = 0 Then
        If Fraction = 0 Then
            Return If(IsNegative, -0#, 0#)
        End If
        Dim FractionRatio = Fraction / FractionBase
        Return If(IsNegative, -1#, 1#) * (2 ^ (1 - ExponentBias)) * FractionRatio
    Else
        If Exponent = 2 * ExponentBias + 1 Then
            If Fraction = 0 Then
                Return If(IsNegative, Double.NegativeInfinity, Double.PositiveInfinity)
            Else
                Return Double.NaN
            End If
        End If
        Dim FractionRatio = Fraction / FractionBase
        Return If(IsNegative, -1#, 1#) * (2 ^ (CInt(Exponent) - ExponentBias)) * (1# + FractionRatio)
    End If
End Function
//C#
public double GetDoubleValue(bool IsNegative, UInt16 Exponent, UInt64 Fraction, 
UInt16 ExponentBias, UInt64 FractionBase)
{
	if (Exponent == 0) {
		if (Fraction == 0) {
			return IsNegative ? -0.0 : 0.0;
		}
		dynamic FractionRatio = Fraction / FractionBase;
		return IsNegative ? -1.0 : 1.0 * (Math.Pow(2, (1 - ExponentBias))) * FractionRatio;
	} else {
		if (Exponent == 2 * ExponentBias + 1) {
			if (Fraction == 0) {
				return IsNegative ? double.NegativeInfinity : double.PositiveInfinity;
			} else {
				return double.NaN;
			}
		}
		dynamic FractionRatio = Fraction / FractionBase;
		return IsNegative ? -1.0 : 1.0 * 
           (Math.Pow(2, (Convert.ToInt32(Exponent) - ExponentBias))) * (1 + FractionRatio);
	}
}

Database primary key and float point

Since float point is approximate number; it is not a good idea to use it as primary key in a database
For example
If we have a table named Customers with a field id with the data type single then
Referring to a one row may result no record even if record is in the database
When we insert 0.4301 as id the real id will be different a lite and may this result unexpected result in database update or select
The flowing sql may result no record and this is depend on the database drive and how it convert numbers form decimal to float point type

Select Customer From Customers where id = 0.4301

Float Numbers and Programming Languages

References

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

NewPast
Lebanon Lebanon
---------------------------
There is a developer behind every piece of code!
DNA is too complex what about it!
No junk DNA; There is a functional role for noncoding DNA

Comments and Discussions

 
PraiseNice article Pin
Avitevet28-Mar-17 16:33
MemberAvitevet28-Mar-17 16:33 
GeneralRe: Nice article Pin
NewPast28-Mar-17 22:40
MemberNewPast28-Mar-17 22:40 
SuggestionImproper referencing Pin
Jochen Arndt3-Jan-17 22:45
mveJochen Arndt3-Jan-17 22:45 
GeneralRe: Improper referencing Pin
NewPast3-Jan-17 23:03
MemberNewPast3-Jan-17 23:03 
GeneralRe: Improper referencing Pin
Jochen Arndt3-Jan-17 23:58
mveJochen Arndt3-Jan-17 23:58 
GeneralMy vote of 5 Pin
AntoineKieffer3-Jan-17 22:14
MemberAntoineKieffer3-Jan-17 22:14 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Article
Posted 6 Jan 2017

Stats

18.7K views
97 downloads
10 bookmarked