Demonstrate the limitations of floating point math by computing 1/3 and storing it in a double variable. Then print the variable with 1/3 and the result of multiplying that variable by 3, 9 and 300 to sixteen decimal places. Do we get the exact results we expected? How do we get this result when 1/3 is infinitely repeating in its decimal form 0.3333...?
Try a similar experiment by assigning 0.2 to a variable. Then with a loop, add it 1000 times to another summation variable that was initialized with 0.0. Print the two-tenths variable, the final summation variable and the two-tenths variable times 1000, all to sixteen decimal places. Do we get the exact answer of 200.0 that we expect in both cases? Why does multiplication result in a better answer than repeated addition?
See [[Floating-point_arithmetic#Accuracy_problems|Floating Point Arithmetic Accuracy Problems]]
Output
$ rustc FloatingPointError.rs
error: unknown format trait `f`
--> FloatingPointError.rs:9:37
|
9 | println!("{}", format!("1/3: {0:.16f}", oneThird));
| ^
|
= note: the only appropriate formatting traits are:
- ``, which uses the `Display` trait
- `?`, which uses the `Debug` trait
- `e`, which uses the `LowerExp` trait
- `E`, which uses the `UpperExp` trait
- `o`, which uses the `Octal` trait
- `p`, which uses the `Pointer` trait
- `b`, which uses the `Binary` trait
- `x`, which uses the `LowerHex` trait
- `X`, which uses the `UpperHex` trait
error: unknown format trait `f`
--> FloatingPointError.rs:10:37
|
10 | println!("{}", format!("one: {0:.16f}", oneThird * 3.0f64));
| ^
|
= note: the only appropriate formatting traits are:
- ``, which uses the `Display` trait
- `?`, which uses the `Debug` trait
- `e`, which uses the `LowerExp` trait
- `E`, which uses the `UpperExp` trait
- `o`, which uses the `Octal` trait
- `p`, which uses the `Pointer` trait
- `b`, which uses the `Binary` trait
- `x`, which uses the `LowerHex` trait
- `X`, which uses the `UpperHex` trait
error: unknown format trait `f`
--> FloatingPointError.rs:11:39
|
11 | println!("{}", format!("three: {0:.16f}", oneThird * 9.0f64));
| ^
|
= note: the only appropriate formatting traits are:
- ``, which uses the `Display` trait
- `?`, which uses the `Debug` trait
- `e`, which uses the `LowerExp` trait
- `E`, which uses the `UpperExp` trait
- `o`, which uses the `Octal` trait
- `p`, which uses the `Pointer` trait
- `b`, which uses the `Binary` trait
- `x`, which uses the `LowerHex` trait
- `X`, which uses the `UpperHex` trait
error: unknown format trait `f`
--> FloatingPointError.rs:12:41
|
12 | println!("{}", format!("hundred: {0:.16f}", oneThird * 300.0f64));
| ^
|
= note: the only appropriate formatting traits are:
- ``, which uses the `Display` trait
- `?`, which uses the `Debug` trait
- `e`, which uses the `LowerExp` trait
- `E`, which uses the `UpperExp` trait
- `o`, which uses the `Octal` trait
- `p`, which uses the `Pointer` trait
- `b`, which uses the `Binary` trait
- `x`, which uses the `LowerHex` trait
- `X`, which uses the `UpperHex` trait
error: unknown format trait `f`
--> FloatingPointError.rs:23:43
|
23 | println!("{}", format!("twoTenths: {0:.16f}", twoTenths));
| ^
|
= note: the only appropriate formatting traits are:
- ``, which uses the `Display` trait
- `?`, which uses the `Debug` trait
- `e`, which uses the `LowerExp` trait
- `E`, which uses the `UpperExp` trait
- `o`, which uses the `Octal` trait
- `p`, which uses the `Pointer` trait
- `b`, which uses the `Binary` trait
- `x`, which uses the `LowerHex` trait
- `X`, which uses the `UpperHex` trait
error: unknown format trait `f`
--> FloatingPointError.rs:24:37
|
24 | println!("{}", format!("sum: {0:.16f}", sum));
| ^
|
= note: the only appropriate formatting traits are:
- ``, which uses the `Display` trait
- `?`, which uses the `Debug` trait
- `e`, which uses the `LowerExp` trait
- `E`, which uses the `UpperExp` trait
- `o`, which uses the `Octal` trait
- `p`, which uses the `Pointer` trait
- `b`, which uses the `Binary` trait
- `x`, which uses the `LowerHex` trait
- `X`, which uses the `UpperHex` trait
error: unknown format trait `f`
--> FloatingPointError.rs:25:37
|
25 | println!("{}", format!("200: {0:.16f}", twoTenths * 1000.f64));
| ^
|
= note: the only appropriate formatting traits are:
- ``, which uses the `Display` trait
- `?`, which uses the `Debug` trait
- `e`, which uses the `LowerExp` trait
- `E`, which uses the `UpperExp` trait
- `o`, which uses the `Octal` trait
- `p`, which uses the `Pointer` trait
- `b`, which uses the `Binary` trait
- `x`, which uses the `LowerHex` trait
- `X`, which uses the `UpperHex` trait
error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
--> FloatingPointError.rs:8:27
|
8 | let mut oneThird:f64 = 1.f64 / 3.f64;
| ^^^
|
help: if intended to be a floating point literal, consider adding a `0` after the period
|
8 | let mut oneThird:f64 = 1.0f64 / 3.f64;
| +
error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
--> FloatingPointError.rs:8:35
|
8 | let mut oneThird:f64 = 1.f64 / 3.f64;
| ^^^
|
help: if intended to be a floating point literal, consider adding a `0` after the period
|
8 | let mut oneThird:f64 = 1.f64 / 3.0f64;
| +
error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
--> FloatingPointError.rs:25:59
|
25 | println!("{}", format!("200: {0:.16f}", twoTenths * 1000.f64));
| ^^^
|
help: if intended to be a floating point literal, consider adding a `0` after the period
|
25 | println!("{}", format!("200: {0:.16f}", twoTenths * 1000.0f64));
| +
error: aborting due to 10 previous errors
For more information about this error, try `rustc --explain E0610`.