Discussion 4/11

Primitive Types

By now we should know about two primitive types:

Here are a few other types we'll see this quarter:

There are quite a few more variations (adding long or short in different ways), but these are the basics.

Maximum size of type int

As we said above, the maximum size of an integer is roughly 2*10^9. Below is a piece of code that shows what happens when we try to make an integer bigger than the maximum.

        #include<iostream>
        using namespace std;

        int main() {
            int x = 2e9;  // Start x at 2000000000
            cout << "x is " << x << "\n";
    
            cout << "Increasing x by 10^8" << "\n";
            x = x + 1e8;  // Make x bigger
            cout << "x is now " << x << "\n";

            cout << "Increasing x by 10^8" << "\n";
            x = x + 1e8;  // Make x bigger
            cout << "x is now " << x << "\n";

            cout << "Increasing x by 10^8" << "\n";
            x = x + 1e8;  // Make x bigger
            cout << "x is now " << x << "\n";
            cout << "What happened here?" << "\n";

            return 0;
        }
      

Decimal precision: float and double

Here's are some programs that are supposed to show the amount of precision we can get out of the float and double types

        // Maximum precision of float and double
        #include <iostream>     // Library for cout, fixed
        #include <iomanip>      // Library for setprecision
        using namespace std;

        int main() {
            cout << fixed << setprecision(5);    
            /* This tells c++ to always output 5 decimal digits
              for every decimal. It doesn't actually
              output anything to the console. */

            float f = 3.1415926535897932384626433;
            cout << f << "\n";
            return 0;
        }

        /*
          Stuff to do:
          (1) Put in many different numbers for setprecision
          (2) Replace float with double and repeat
          */
      

Size of float

        // This program shows the maximum value of a float variable
        #include <iostream>     // Library for cout, fixed
        #include <iomanip>      // Library for setprecision
        using namespace std;
        
        int main() {
            float f = 1e36;
            cout << f << "\n";
            f = 10*f;    // now f is 1e37
            cout << f << "\n";
            f = 10*f;    // now f is 1e38
            cout << f << "\n";
            f = 10*f;    // now f is 1e39
            cout << f << "\n";
            f = 10*f;    // now f is 1e40
            cout << f << "\n";
        
            return 0;
        }
      

Size of double

        // This program shows the maximum value of a double variable
        #include <iostream>     // Library for cout, fixed
        #include <iomanip>      // Library for setprecision
        using namespace std;
        
        int main() {
            double d = 1e305;
            cout << d << "\n";
            d = 10*d;    // now d is 1e306
            cout << d << "\n";
            d = 10*d;    // now d is 1e307
            cout << d << "\n";
            d = 10*d;    // now d is 1e308
            cout << d << "\n";
            d = 10*d;    // now d is 1e309
            cout << d << "\n";
            d = 10*d;    // now d is 1e310
            cout << d << "\n";
            
            return 0;
        }
      

Arithmetic in c++

When working with numbers in c++, we can do arithmetic via +, -, *, and /. These work mostly as you would expect, with one big exception in integer division vs. decimal division.

Rules for integer vs. decimal arithmetic: If both inputs are integer-types, then the output will be an integer-type. If at least one input is a decimal-type, then the output will be a decimal-type.

When c++ converts a decimal to an integer, it will always round towards 0.

Note: The ^ operator does not perform exponentiation. In c++, ^ means an entirely different thing that we don't talk about in PIC10A. If you want to take powers of numbers, you can #include<cmath> and use the pow function (we'll learn this later though. Don't worry about it now).

Integer Division vs. Decimal Division

Here's an example of integer division vs decimal division.

#include<iostream>
using namespace std;

int main() {

    // This program calculates 5/3 in a few different ways.
    // Notice how the types of the variables change the answer.
    int x = 5;
    cout << x/3 << "\n";
    cout << x/3.0 << "\n";
    cout << -x/3 << "\n";
    cout << -x/3.0 << "\n";

    double y = 5.0;
    cout << y/3 << "\n";
    cout << y/3.0 << "\n";
    cout << -y/3 << "\n";
    cout << -y/3.0 << "\n";
                            
    return 0;
}

The Modulus Operator

Suppose that a and b are two integers. Then a%b will do the division a/b, and return the remainder.

// Modulus example:
#include<iostream>
using namespace std;

int main() {
    int dividend;
    int divisor;
    cout << "Input two integers: \n";
    cin >> dividend >> divisor;
    cout << dividend << "/" << divisor << " = " << dividend / divisor
        << " with remainder " << dividend%divisor << ".\n";
    return 0;
}

Why do we like the modulus operator?

Type Casting

Let's look at the following code:

#include<iostream>
using namespace std;

int main() {

    int x;
    x = 1.7;
    cout << x << "\n";
    
    return 0;
}
      

What happens to x here? We declared at the beginning of the code that x would store integer values. Now we're trying to store a decimal value. The way c++ works, the type of x will never change (it will always store an integer). So instead c++ will convert 1.7 into an integer, then store that value into x. Like we said above, c++ converts decimals into integers by rounding towards 0.

Formal word for this conversion is Type Casting. In this particular problem we cast a double into an int.

Manually Type Casting

We just gave an example where c++ will automatically cast a decimal into an integer. We can also manually force c++ to typecast a variable. Here is the syntax:

TYPE1 X = VALUE;  // Here X is declared to be TYPE1
TYPE2 Y = (TYPE2)X;  // The code '(TYPE2)X' converts X to TYPE2 and returns that value

Note: This does not change the value of X. The value of X is used to calculate Y, but X is not changed. Here's an actual program to show how type casting works:

// Type casting example:
#include <iostream>
#include <iomanip>
using namespace std;

int main() {
   cout << fixed << setprecision(4); // cout will always give 4 decimal digits
              // helps see the difference between decimal and integer
   int a = 4;
   double c = 5.1203;
   cout << "a=" << a << "\n"
        << "(double)a=" << (double)a << "\n" 
        << "c=" << c << "\n" 
        << "(int)c=" << (int)c << "\n";
   return 0;
}

Type Casting Problems

For each of these problems, the question is the same. What does the program output? The key is to figure out if the division is using integers or decimals.

Problem 1

#include <iostream>
using namespace std;

int main() {
    int a = 4;
    int b = 3;
    double c = a / b;
    cout << c << "\n";
    return 0;
}

Problem 2

#include <iostream>
using namespace std;

int main() {
    int a = 4;
    int b = 3;
    double c = (double)(a/b);
    cout << c << "\n";
    return 0;
}

Problem 3

#include <iostream>
using namespace std;

int main() {
    int a = 4;
    int b = 3;
    double c = ((double)a / b);
    cout << c << "\n";
    return 0;
}

Problem 4

#include <iostream>
using namespace std;

int main() {
    int a = 4;
    int b = 3;
    double c = (a / (double)b);
    cout << c << "\n";
    return 0;
}

Problem 5

#include <iostream>
using namespace std;

int main() {
    int a = 4;
    int b = 3;
    double c = (double)a/b;
    cout << c << "\n";
    return 0;
}

Problem 6

#include <iostream>
using namespace std;

int main() {
    int a = 4;
    int b = 3;
    double c = (double) a/b;
    cout << c << "\n";
    return 0;
}

All those problems have been about converting ints into doubles. Let's go the other way.

(Note: 7.9/0.9 is approximately 8.7)

Problem 7

#include <iostream>
using namespace std;

int main() {
    double a = 7.9;
    double b = 0.9;
    int c = a / b;
    cout << c << "\n";
}

Problem 8

#include <iostream>
using namespace std;

int main() {
    double a = 7.9;
    double b = 0.9;
    int c = (int)(a / b);
    cout << c << "\n";
}

Problem 9

#include <iostream>
using namespace std;

int main() {
    double a = 7.9;
    double b = 0.9;
    int c = (double)(a / b);
    cout << c << "\n";
}

Problem 10

#include <iostream>
using namespace std;

int main() {
    double a = 7.9;
    double b = 0.9;
    int c = ((int)a / b);
    cout << c << "\n";
}

Problem 11

#include <iostream>
using namespace std;

int main() {
    double a = 7.9;
    double b = 0.9;
    int c = (a / (int)b);
    cout << c << "\n";
}

Practice Problems

  1. Write a program that inputs a fraction (get a numerator and denominator using cin), and outputs the same number, written as a mixed fraction.
      Ex: If I input 11/5, the program should output 2 + 1/5
          If I input 17/3, the program should output 5 + 2/3
    You can assume that all numbers are positive (it makes the final program a bit less messy).
  2. Write a program that inputs a decimal number, and ouputs the integer part of that number.
        Ex: If I input 5.1232309 I should output 5.
  3. Write a program that inputs a decimal number, and ouputs the decimal part of that number.
        Ex: If I input 5.1232309 I should output 0.1232309.

If we have extra time

Let's play around with some other type-casting (not just ints and doubles). Write code to try to understand the following:

  1. int to char, char to int
  2. int to bool, bool to int
  3. Any primitive type to string, or the other way around