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 int
s 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 double
s and they are not equal to each
other
Round-off Errors¶
there are infinitely many real numbers, but only a finite number of
double
s, 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 double
s
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