# Comparisons

This tutorial covers comparing signed and unsigned integers, and comparing floating point numbers (`double`).

We’ll explain how to fix errors like this:

``````error: comparison between signed and unsigned integer expressions
``````

## Signed and unsigned integer comparisons

Example from `stats.cpp`:

``````double sum(vector<double> v) {
double total = 0;
for (int i = 0; i < v.size(); ++i) {
total += v[i];
}
}
``````

Compile and get this error:

``````\$ make stats_tests.exe
g++ -Wall -Werror -pedantic -g --std=c++17 stats_tests.cpp stats.cpp p1_library.cpp -o stats_tests.exe
stats.cpp: In function 'double sum(std::vector<double>)':
stats.cpp:17:21: error: comparison between signed and unsigned integer expressions [-Werror=sign-compare]
for (int i = 0; i < v.size(); ++i) {
~~^~~~~~~~~~
cc1plus: all warnings being treated as errors
make: *** [stats_tests.exe] Error 1
``````

The problem is `v.size()` returns a `size_t` type, which is an alias for an unsigned integer type. The loop variable `i` is an `int` type. The types don’t match.

### Solution 1: `size_t`

Change `int i` to `size_t i`. Now, the types match and the compiler is happy.

``````double sum(vector<double> v) {
double total = 0;
// primer-spec-highlight-start
for (size_t i = 0; i < v.size(); ++i) {
// primer-spec-highlight-end
total += v[i];
}
}
``````

### Solution 2: `static_cast<>()`

Cast `v.size()` to an `int`. Again, the types match and the compiler is happy.

``````double sum(vector<double> v) {
double total = 0;
// primer-spec-highlight-start
for (int i = 0; i < static_cast<int>(v.size()); ++i) {
// primer-spec-highlight-end
total += v[i];
}
}
``````

## Floating point comparisons

Another comparison error you may encounter occurs when you compare two floating point numbers, like `double`s. Floating point numbers have limited precision. Due to rounding errors, two floating point numbers we expect to be equal may be slightly different.

For example:

``````//test.cpp
#include <iostream>
using namespace std;

int main() {
double x = 1.0 / 3.0;
double y = 1.0 - (2.0 / 3.0);
cout << "x=" << x << endl;
cout << "y=" << y << endl;
if (x == y) {
cout << "equal" << endl;
} else {
cout << "not equal" << endl;
}
}
``````

Compile and run. The two numbers look the same, but when we compare them, they are not equal! Notice that `x` and `y` are rounded to 6 decimal places by default.

``````\$ g++ test.cpp -o test.exe
\$ ./test.exe
x=0.333333
y=0.333333
not equal
``````

Let’s look at the full precision. Modify your program to look like this.

``````//test.cpp
#include <iostream>
#include <limits>
using namespace std;

int main() {
double x = 1.0 / 3.0;
double y = 1.0 - (2.0 / 3.0);
// primer-spec-highlight-start
cout.precision(std::numeric_limits<double>::max_digits10);
// primer-spec-highlight-end
cout << "x=" << x << endl;
cout << "y=" << y << endl;
if (x == y) {
cout << "equal" << endl;
} else {
cout << "not equal" << endl;
}
}
``````

Compile and run. Notice that `x` and `y` are no longer rounded to 5 decimal places. We can see that they are slightly different.

``````\$ g++ test.cpp -o test.exe
\$ ./test.exe
x=0.33333333333333331
y=0.33333333333333337
not equal
``````

Next, we’ll compare within a tolerance `epsilon`, instead of an exact comparison. Again, modify your program:

• Use an expression like `if (abs(x - y) < epsilon)` in the example below.
• Note that the `#include <cmath>` is required to ensure the proper version of `abs()` is available. (Your code will not compile on the autograder without this.)
``````//test.cpp
#include <iostream>
// primer-spec-highlight-start
#include <cmath>
// primer-spec-highlight-end
#include <limits>
using namespace std;

// Precision for floating point comparison
const double epsilon = 0.00001;

int main() {
double x = 1.0 / 3.0;
double y = 1.0 - (2.0 / 3.0);
cout.precision(std::numeric_limits<double>::max_digits10);
cout << "x=" << x << endl;
cout << "y=" << y << endl;
// primer-spec-highlight-start
if (abs(x - y) < epsilon) {
// primer-spec-highlight-end
cout << "equal" << endl;
} else {
cout << "not equal" << endl;
}
}
``````

Compile and run. Notice that the comparison now reports equal.

``````\$ g++ test.cpp -o test.exe
\$ ./test.exe
x=0.33333333333333331
y=0.33333333333333337
equal
``````