# CSE202: Lecture 10AThe Ohio State University1 Numerical Error.

## Presentation on theme: "CSE202: Lecture 10AThe Ohio State University1 Numerical Error."— Presentation transcript:

CSE202: Lecture 10AThe Ohio State University1 Numerical Error

CSE202: Lecture 10AThe Ohio State University2 Data Types: Floating Point Numbers (1) Floating-point numbers have a decimal point, and they can also be signed or unsigned. There are three types: float, double, or long double. –The differences between these are their supported range and precision.

CSE202: Lecture 10AThe Ohio State University3 Data Types: Floating Point Numbers (2) To represent a floating point number: –float uses 32 bits (4 bytes) –double uses 64 bits (8 bytes) –long double uses 128 bits (16 bytes) The tradeoff is storage vs. precision and range What exactly is the precision and range, and how are floating point numbers represented in binary format? IEEE 754 Standard

CSE202: Lecture 10AThe Ohio State University4 Numerical Error (1) // example of numerical error #include using namespace std; int main() { double x(0.7); // initialize x to 0.7 cout << "(0.7-0.6)*10.0 - 1.0 = " << (x-0.6)*10.0 - 1.0 << endl; return 0; }

CSE202: Lecture 10AThe Ohio State University5 > numerical_error1.exe (0.7-0.6)*10.0 - 1.0 = -2.22045e-16 > … double x(0.7); // initialize x to 0.7 cout << "(0.7-0.6)*10.0 - 1.0 = " << (x-0.6)*10.0 - 1.0 << endl; …

CSE202: Lecture 10AThe Ohio State University6 Numerical Error (2) // print 18 significant digits #include using namespace std; int main() { double x(0.7); // initialize x to 0.7 cout << "x = " << x << endl; cout.precision(18); // output 18 significant digits cout << "x = " << x << endl; return 0; }

CSE202: Lecture 10AThe Ohio State University7 > numerical_error2.exe x = 0.7 x = 0.699999999999999956 > … double x(0.7); // initialize x to 0.7 cout << "x = " << x << endl; cout.precision(18); // output 18 significant digits cout << "x = " << x << endl; …

CSE202: Lecture 10AThe Ohio State University8 Numerical Error Computers store floating point numbers in binary (base 2 or as 0’s and 1’s). There is no way to represent 0.7 precisely in base 2. There is no way to represent 0.1 precisely in base 2!

CSE202: Lecture 10AThe Ohio State University9 Numerical Error (3)... int main() { cout.precision(18); // output 18 significant digits cout << "0.0 = " << 0.0 << endl; cout << "0.1 = " << 0.1 << endl; cout << "0.2 = " << 0.2 << endl; cout << "0.3 = " << 0.3 << endl; cout << "0.4 = " << 0.1 << endl; cout << "0.5 = " << 0.5 << endl; cout << "0.6 = " << 0.6 << endl; cout << "0.7 = " << 0.7 << endl; cout << "0.8 = " << 0.8 << endl; cout << "0.9 = " << 0.9 << endl; cout << "1.0 = " << 1.0 << endl; return 0; }

CSE202: Lecture 10AThe Ohio State University10 > numerical_error3.exe 0.0 = 0 0.1 = 0.100000000000000006 0.2 = 0.200000000000000011 0.3 = 0.299999999999999989 0.4 = 0.100000000000000006 0.5 = 0.5 0.6 = 0.599999999999999978 0.7 = 0.699999999999999956 0.8 = 0.800000000000000044 0.9 = 0.900000000000000022 1.0 = 1 > … cout.precision(18); // output 18 significant digits cout << "0.0 = " << 0.0 << endl; cout << "0.1 = " << 0.1 << endl; …

CSE202: Lecture 10AThe Ohio State University11 Floating Point Accuracy in Conditional Expressions

CSE202: Lecture 10AThe Ohio State University12 Floating Point Accuracy Issue (1) WARNING: when comparing floating point numbers (of any kind: float, double, long double, …) you cannot use the == operator reliably This is a computer limitation. Two numbers, which should be equal, may not be stored as precisely equal in the computer. –Remember numerical accuracy: how would 0.1 be represented in binary notation? It is not possible to add negative powers of 2’s to get an exact representation of 0.1 –Instead, we only get a very good approximation but is still NOT exactly equal to 0.1

CSE202: Lecture 10AThe Ohio State University13 Floating Point Accuracy Issue (2) Check it out: float x(0.1); double y(0.1); cout << setprecision(20) << x << endl; cout << setprecision(20) << y << endl; You should also notice how the doubly precise representation for y gives a far better approximation of 0.1 than that of x, which is only represented by single precision! Regardless of how closely the number is to 0.1, it certainly is not equivalent

CSE202: Lecture 10AThe Ohio State University14 Floating Point Accuracy Issue (3) float x(0.1); double y(0.1); if (x == y) { cout << “x equals y” << endl; } The above cout statement will never execute because x and y are not equal (they’re VERY close, but not equal), and therefore the if- statement will not succeed!!

CSE202: Lecture 10AThe Ohio State University15 Be Consistent Always use the same data type for floating point variables. In C++, floating point expressions default to double. Consider the expression: cout << 4 * 9.34 << endl; The number 9.34 is not stored in a variable, but it still needs to be stored SOMEWHERE in memory. So what type is it? By default, C++ stores is as a double. This is why we ONLY use double (and not float or long double ) in this course!

CSE202: Lecture 10AThe Ohio State University16 Floating Point Accuracy Issue (3) double x(0.1); double y(0.1); if (x == y) { cout << “x equals y” << endl; } The above cout statement will execute since x equals y.

CSE202: Lecture 10AThe Ohio State University17 accuracyError.cpp // error caused by lack of accuracy #include using namespace std; int main() { double x(0.1); double y(1e-6); // y = 10^(-6) if (x == (1e5*y)) // if (x == 10^5*10^(-6)) { cout << x << " equals 1e5 x " << y << endl; } else { cout << x << " does not equal 1e5 x " << y << endl; } return 0; }

CSE202: Lecture 10AThe Ohio State University18 > accuracyError.exe 0.1 does not equal 1e5 x 1e-06 > … double x(0.1); double y(1e-6); // y = 10^(-6) if (x == (1e5*y)) // if (x == 10^5*10^(-6)) { cout << x << " equals 1e5 x " << y << endl; } else { cout << x << " does not equal 1e5 x " << y << endl; } …

CSE202: Lecture 10AThe Ohio State University19 Floating Point Accuracy Issue (4) Instead of checking: if (operand1 == operand2) See if the difference between them is small enough to assume truth: if (abs(operand1 - operand2) < 0.000001)

CSE202: Lecture 10AThe Ohio State University20 Floating Point Accuracy Issue (5) Or, better yet: if (abs(operand1 – operand2) < EPSILON) 1.where EPSILON is some constant you have previously declared, and 2.abs() is the absolute value function for floating point numbers available by including the cmath library

CSE202: Lecture 10AThe Ohio State University21 accuracyExample.cpp // approximating numbers near zero #include using namespace std; int main() { double EPSILON(1e-12); double x(0.1); double y(1e-6); // y = 10^(-6) if (abs(x - (1e5*y)) < EPSILON) // if (abs(x-10^5*10^(-6)) < EPSILON) { cout << x << " equals 1e5 x " << y << endl; } else { cout << x << " does not equal 1e5 x " << y << endl; } return 0; }

CSE202: Lecture 10AThe Ohio State University22 > accuracyExample.exe 0.1 equals 1e5 x 1e-06 > double EPSILON (1e-12); double x(0.1); double y(1e-6); // y = 10^(-6) if (abs(x - (1e5*y)) < EPSILON) // if (abs(x-10^5*10^(-6)) < EPSILON) { cout << x << " equals 1e5 x " << y << endl; } else { cout << x << " does not equal 1e5 x " << y << endl; }

CSE202: Lecture 10AThe Ohio State University23 Type Casting

CSE202: Lecture 10AThe Ohio State University24 Type Casting (1) Review: We saw one form of coercion through assignment: int a, b; double c; c = a * b; a * b is an integer but the result is converted to a double when assigned to c. This type of coercion is implicit

CSE202: Lecture 10AThe Ohio State University25 Type Casting (2) There is another type of coercion, called “type casting”, which allows the programmer to explicitly force a data type onto an expression. The cast operator is: dataType(expression)

CSE202: Lecture 10AThe Ohio State University26 Type Casting (3) Example: int x = 5; double y = log(double(x)); Alternative format (C version): int x = 5; double y = log((double)(x));

CSE202: Lecture 10AThe Ohio State University27 logError.cpp // example of cmath function log #include using namespace std; int main() { int value(0); cout << "Enter value: "; cin >> value; // log(value) generates a compiler error cout << "At 10% interest, it will take " << log(value)/log(1.1) << " years for a \$1 investment to be worth \$" << value << "." << endl; return 0; }

CSE202: Lecture 10AThe Ohio State University28 > g++ logError.cpp –o logError.exe Compiling logError.cpp into logError.exe. logError.cpp: In function `int main()': logError.cpp:16: call of overloaded `log(int&)' is ambiguous /usr/include/iso/math_iso.h:52: candidates are: double log(double) /usr/local/include/g++-v3/bits/std_cmath.h:333: long double std::log(long double) /usr/local/include/g++-v3/bits/std_cmath.h:323: float std::log(float) … // log(value) generates a compiler error cout << "At 10% interest, it will take " << log(value)/log(1.1) << " years for a \$1 investment to be worth \$" << value << "." << endl; …

CSE202: Lecture 10AThe Ohio State University29 logTypeCast.cpp #include using namespace std; int main() { int value(0); cout << "Enter value: "; cin >> value; // type cast value to double cout << "At 10% interest, it will take " << log(double(value)) /log(1.1) << " years for a \$1 investment to be worth \$" << value << "." << endl; return 0; }

CSE202: Lecture 10AThe Ohio State University30 > logExample.exe Enter value: 10 At 10% interest, it will take 24.1589 years for a \$1 investment to be worth \$10. > … // type cast value to double cout << "At 10% interest, it will take " << log(double(value)) /log(1.1) << " years for a \$1 investment to be worth \$" << value << "." << endl; …

CSE202: Lecture 10AThe Ohio State University31 lower2Upper.cpp... int main() { int ascii_A(0), ascii_B(0); char a, b; cout << "Enter initials (2 char): "; cin >> a >> b ; cout << "Ascii " << a << ": " << int(a) << endl; cout << "Ascii " << b << ": " << int(b) << endl; ascii_A = int(a)-32; ascii_B = int(b)-32; cout << "Initials: "; cout << char(ascii_A) << char(ascii_B) << endl; return 0; }

ASCII Code CSE202: Lecture 10AThe Ohio State University32 CodeChar 32Space 33! 34" 35# 36\$ 37% 38& 39' 40( 41) …… CodeChar 480 491 502 513 524 535 546 557 568 579 …… CodeChar 65A 66B 67C 68D 69E 70F 71G 72H 73I 74J …… CodeChar 97a 98b 99c 100d 101e 102f 103g 104h 105i 106j ……

CSE202: Lecture 10AThe Ohio State University33 … cout << "Ascii " << a << ": " << int(a) << endl; cout << "Ascii " << b << ": " << int(b) << endl; ascii_A = int(a)-32; ascii_B = int(b)-32; cout << "Initials: "; cout << char(ascii_A) << char(ascii_B) << endl; … > lower2Upper.exe Enter initials (2 char): dj Ascii d: 100 Ascii j: 106 Initials: DJ >