cse202: lecture 10athe ohio state university1 numerical error
TRANSCRIPT
CSE202: Lecture 10A The Ohio State University 1
Numerical Error
CSE202: Lecture 10A The Ohio State University 2
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 10A The Ohio State University 3
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 10A The Ohio State University 4
Numerical Error (1)// example of numerical error
#include <iostream>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 10A The Ohio State University 5
> 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 10A The Ohio State University 6
Numerical Error (2)// print 18 significant digits
#include <iostream>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 10A The Ohio State University 7
> numerical_error2.exex = 0.7x = 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 10A The Ohio State University 8
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 10A The Ohio State University 9
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 10A The Ohio State University 10
> numerical_error3.exe0.0 = 00.1 = 0.1000000000000000060.2 = 0.2000000000000000110.3 = 0.2999999999999999890.4 = 0.1000000000000000060.5 = 0.50.6 = 0.5999999999999999780.7 = 0.6999999999999999560.8 = 0.8000000000000000440.9 = 0.9000000000000000221.0 = 1>
… cout.precision(18); // output 18 significant digits cout << "0.0 = " << 0.0 << endl; cout << "0.1 = " << 0.1 << endl;…
CSE202: Lecture 10A The Ohio State University 11
Floating Point Accuracy in Conditional Expressions
CSE202: Lecture 10A The Ohio State University 12
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 10A The Ohio State University 13
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 10A The Ohio State University 14
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 10A The Ohio State University 15
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 10A The Ohio State University 16
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 10A The Ohio State University 17
accuracyError.cpp// error caused by lack of accuracy#include <iostream>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 10A The Ohio State University 18
> accuracyError.exe0.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 10A The Ohio State University 19
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 10A The Ohio State University 20
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 10A The Ohio State University 21
accuracyExample.cpp// approximating numbers near zero
#include <iostream>#include <cmath>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 10A The Ohio State University 22
> accuracyExample.exe0.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 10A The Ohio State University 23
Type Casting
CSE202: Lecture 10A The Ohio State University 24
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 10A The Ohio State University 25
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 10A The Ohio State University 26
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 10A The Ohio State University 27
logError.cpp// example of cmath function log#include <iostream>#include <cmath>
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 10A The Ohio State University 28
> g++ logError.cpp –o logError.exeCompiling 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 10A The Ohio State University 29
logTypeCast.cpp#include <iostream>#include <cmath>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 10A The Ohio State University 30
> 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 10A The Ohio State University 31
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 10A The Ohio State University 32
Code Char
32 Space
33 !
34 "
35 #
36 $
37 %
38 &
39 '
40 (
41 )
… …
Code Char
48 0
49 1
50 2
51 3
52 4
53 5
54 6
55 7
56 8
57 9
… …
Code Char
65 A
66 B
67 C
68 D
69 E
70 F
71 G
72 H
73 I
74 J
… …
Code Char
97 a
98 b
99 c
100 d
101 e
102 f
103 g
104 h
105 i
106 j
… …
CSE202: Lecture 10A The Ohio State University 33
… 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
>