Floating Point
Floating Point Numbers
There are other types of numbers other than integers:
- Rational numbers from ratio ≃ fraction like 10/3.
- Real numbers like π.
Scientific Notation
Binary numbers in scientific notation. The digit to the left of the decimal point is always 1. The normalized form would be:
- Where x is the fraction and y is the exponent
IEEE 754 floating point standard. They are templates. A way of encoding base 2 scientific notation.
Single precision uses 4 bytes 1 bit for the sign, 8 bits for the exponents, and 23 bits for the fraction.
- The way the exponent is stored is in a bias form. This means that we add a bias (127) to the exponent value, and it makes it an unsigned integer. For example, --> exponent = . We do this because it simplifies the hardware that is used to compare exponents.
Steps to encode
Example conversion from decimal into binary.
First, we convert the number before the period: Second, we convert the fraction
- Decide if its greater or equal to 0.5. Since it is not, the first digit in the fraction would be zero.
- Double the digit: . Since it still not , we generate another 0.
- We double again to get which is , so we generate a one.
- The next value would be
We can do this inifinitely to increase precision. At the end our value is
Example encoding into single precision representation
Encoding:
- sign = 0
- exponent = 10000000 (because we add the bias to our exponent value of 1: that way <-- our exponent)
- Fraction: 1001001000011111101101
Note: the leading 1 in the fraction is ommitted.
C Representation
#include <stdio.h>
int main(void) {
float x;
scanf("%f", &x);
unsigned *p = (unsigned *) &x;
for (int i = 31; i >= 0; i--) {
printf("%c", (*p & (1 << i)) ? '1' : '0');
if (i == 31 || i == 23) { printf(" "); }
}
printf("\n");
return 0;
}
Running the program
$ gcc explain.c
$ echo '-18.8203125' | ./a.out
Output
1 10000011 00101101001000000000000
Special cases
- Zero
- Infinity (1/0)
- Negative infinity (-1/0)
- Not a number (
NaN) (0/0 or )
Encodings
-
Exponent = 0, Fraction = 0, Object = Zero Say you have a region of memory that is filled with zero bits. If you use any of that region to initialize a floating point value, it would represent zero. Which is very nice
-
Exponent = 0, Fraction = >0, Object = Denormalized number Allows more precise representations of values that are very close to zero. Something like
-
Exponent = 1-254, Fraction = anything, Object = Normalized number (Floating point number) Allows more precise representations of values that are very close to zero.
-
Exponent = 255, Fraction = 0, Object = infinity
-
Exponent = 255, Fraction = >0, Object = NaN (not a number)
Precision
Single precision = 4 bytes
- sign = 1 bit, exponent = 8 bits, fraction = 23 bits
Double precision = 8 bytes
- sign = 1 bit, exponent = 11 bits, fraction = 52 bits
Addition
Flowchart
- Start
- Compare components: shift smaller number to right until exponents match
- Add fractions
- Normalize the sum: increase/decrease exponent
- Overflow/underflow ? Throw Exception : Move on to step 7
- Round fraction to appropriate numeber of bits
- Normalized ? Move onto step 8 : Go to step 4
- Done
Example We have 4 significant digits in the encoding:
In scientific notation
Bring the lower number on the same exponent as the higher number, meaning you must round to 4 significant digits
Add the fractions
Adjust exponent
Round to 4 significant digits:
Multiplication
Flowchart
- Start
- Add exponents
- Multiply fractions
- Normaize the product: either increase or decrease exponent
- Overflow/underflow ? Throw exception : Move onto step 6
- Round fraction to appropriate number of bits
- Normalized ? Move onto step 8 : Go back to step 4
- Set sign
- Done
Linked from Computer System Fundamentals