Strange Arithmetic¶
What gets printed?¶
int x = 1/2 + 1/3 + 1/4;
cout << x << "\n";
What gets printed?¶
double x = 1/2 + 1/3 + 1/4;
cout << x << "\n";
dividing two ints always returns an int (truncated)
What gets printed?¶
double x = 1.0/2 + 1/3 + 1/4;
cout << x << "\n";
What gets printed?¶
double x = 1.0/2.0 + 1.0/3.0 + 1.0/4.0;
cout << x << "\n"; // 1.08333
What’s the value and type?¶
double(1)/2 evaluates to the double 0.5
double(1/2) evaluates to the double 0.0
1/double(3) evaluates to the double 0.33333
double(1)/double(4) evaluates to the double 0.25
Dividing by 0 in math class¶
in math class, what is \(\frac{3}{0}\)?
answer (in math class): division by 0 is undefined, you just can’t do it
(in math class) it’s just like trying divide 3 by a rectangle — you can’t do that because it’s undefined
Division by 0 (int literals)¶
cout << "2 / 0 = " << (2 / 0);
compiler error (for us!)
error: division by zero
Division by 0 (int variables)¶
int n = 2;
int zero = 0;
cout << "n / zero = " << (n / zero);
// Run-time error: Floating point exception (core dumped)
Division by 0 (int variables)¶
int n = 2;
int five = 5;
cout << "five / (n - n) = " << (five / (n - n));
// compiler error (for us!): error: division by zero
Division by 0.0 (doubles)¶
cout << "4.0 / 0.0 = " << (4.0 / 0.0);
// 4.0 / 0.0 = inf (!)
inf is a value representing positive infinity
cout << "0.0 / 0.0 = " << (0.0 / 0.0);
// 0.0 / 0.0 = -nan (!)
nan is a value representing “not a number”
nan and inf are both doubles and they are not equal to each
other
Round-off Errors¶
there are infinitely many real numbers, but only a finite number of
doubles, so round-off errors are unavoidable
cout << 1.0 / 3.0;
// 0.333333
0.333333 is a little less than the true value \(\frac{1}{3} =
0.3333\ldots\)
for example:
double a = 1.0 - (2.0/3.0);
double b = 1.0 / 3.0;
cout << "a = " << a << "\n";
cout << "b = " << b << "\n";
cout << "a - b = " << (a - b) << "\n";
if (a == b) {
cout << "no round-off error\n";
} else {
cout << "round-off error\n";
}
the printed values of a and b look the same, but their not!
when << prints a double, it prints a certain number of digits by
default; you can change the number of printed digits using setprecision,
e.g.:
double a = 1.0 - (2.0/3.0);
double b = 1.0 / 3.0;
cout << "a = " << setprecision(20) << a << "\n";
cout << "b = " << setprecision(20) << b << "\n";
cout << "a - b = " << (a - b) << "\n";
if (a == b) {
cout << "no round-off error\n";
} else {
cout << "round-off error\n";
}
now you can see that a and b are different
for most practical applications, though, a and b are so close that it
is fine to treat them as equal
Comparing Floating Point Numbers¶
x == y is often a bad way of comparing two doubles
round-off errors might make x and y not exactly equal
use abs(x - y) < EPSILON, where EPSILON is a small double you
define (e.g. maybe 0.000001)
Computer arithmetic is not regular arithmetic!¶
in mathematics these facts are true
for any real number \(x\)
- if \(x > 0\) then \(x + 1 > 0\)
- \(|x| \geq 0\)
- \(x = x\)
- if \(f(1) = 2\), then \(f(1) + f(1) = 2 + 2 = 4\)
but these are not all true in C++!
Computer Arithmetic Can be Strange¶
if \(x > 0\) then \(x + 1 > 0\)
int a = 2147483647;
int b = 1;
cout << a + b;
// -2147483648
2147483647 is the max int (\(2^{31} - 1\))
-2147483648 is the min int (\(-2^{31}\))
adding 1 to the max int gives you the min int
Computer Arithmetic Can be Strange¶
\(|x| \geq 0\)
cout << abs(-2147483648);
-2147483648 is the min int
due to 0, there is one more negative int than positive int
so -2147483648 has no matching positive int
Computer Arithmetic Can be Strange¶
\(x = x\)
double x = 0.0 / 0.0;
bool same = (x == x);
cout << same;
prints 0, which means x == x is false (!)
0.0 / 0.0 is nan, i.e. “not a number”
nan != nan
Computer Arithmetic Can be Strange¶
if \(f(1) = 2\), then \(f(1) + f(1) = 2 + 2 = 4\)
consider this C++ function:
int count = 0;
int f(int n) {
++count;
return n + count;
}
then f(1) + f(1) evaluates to 5 (!)
you could also have a completely unpredictable function like this
int g(int n) {
int a;
cin >> a;
return n + a;
}
we have no idea what g(1) returns!!
we can even have functions that don’t return at all, e.g.:
int h(int n) {
if (n <= 1) cmpt::error("oops");
return n + 1;
}
h(1) does not return any value
instead, it throws an exception
Advice¶
important floating point calculations must be done with great care
however, we will mostly ignore round-off errors in this course and hope they don’t cause problems