# Advanced Introduction to C++, Scientific Computing and Machine Learning

Claudius Gros, WS 2021/22

Institut für theoretische Physik
Goethe-University Frankfurt a.M.

# primitive data types

• int, double, char, ... are primitive (predefined) data types
arbitrary complex data types may be defined by the user
• String  is (however) an object, like everything else
• one byte is 8 bits (a boolean would correspond to a bit)
all data must be however addressable
Typ Size Domain Example
bool 1 {true, false} bool b = true;
char 1 [0x0000, 0xFFFF] char c = 'a';
byte 1 [−27, 27−1] = [−128, 127] byte b = 4;
short int 2 [−215, 215−1] = [−32,768, 32767] short int s = 12345;
int 4 [−231, 231−1] =
[−2,147,483,648, 2,147,483,647]
int i = 17;
long int8 [−263, 263−1] long int l =8L;
float 4 [1.40239846 ⋅ 10–45, 3.40282347 ⋅ 1038] float f = 3.14F ;
double 8 [4.94065645841246544 ⋅ 10–324,
1.79769131486231570 ⋅ 10308]
double d = 3.14

• short / long for specialized applications only
• float not used anymore, standard is
double for floating point operations
• 32/64 bits (int/double) used for memory addressing by 32/64 bit processors,
$\rightarrow$ memory restrictions

# example: primitive data types

• sizeof() may depend on CPU used; may be used for any object
returns the number of bytes used (one byte is 8 bits)
• C++ is nice to complex numbers,
typedef defines a new data type
• M_PI $= \pi$
#include <iostream>
#include <stdio.h>
#include <complex>  // complex numbers
using namespace std;

int main()
{
int intArray[5] = { 16, 2, 77, 40, 12071 };
double doubleArray[10];
//
printf("size of        bool   : %4d\n",(int)sizeof(bool));
//
printf("size of        char   : %4d\n",(int)sizeof(char));
printf("\n");
printf("size of        int    : %4d\n",(int)sizeof(int));
printf("size of  short int    : %4d\n",(int)sizeof(short int));
printf("size of   long int    : %4d\n",(int)sizeof(long int));
printf("\n");
printf("size of        float  : %4d\n",(int)sizeof(float));
printf("size of        double : %4d\n",(int)sizeof(double));
printf("size of   long double : %4d\n",(int)sizeof(long double));  // what is that?
printf("\n");
printf("size of      intArray : %4d\n",(int)sizeof(intArray));
printf("size of   doubleArray : %4d\n",(int)sizeof(doubleArray));
//
typedef complex<double> doubleComplex;
printf("\n");
printf("size of doubleComplex : %4d\n",(int)sizeof(doubleComplex));
printf("\n");
//
//
printf("=== =============================== ===\n");
printf("=== having fun with complex numbers ===\n");
printf("=== =============================== ===\n");
doubleComplex a(1.11,2.22),b(0,1);
printf("\n");
printf("a         = %f + %f i\n",a.real(),a.imag());
printf("\n");
//
cout << "a         = " << a       << "\n";
cout << "b         = " << b       << "\n";

cout << "a + b     = " << a + b   << "\n";
cout << "a * b     = " << a * b   << "\n";
cout << "a / b     = " << a / b   << "\n";
cout << "|a|       = " << abs(a)  << "\n";

cout << "a*        = " << conj(a) << "\n";
cout << "norm(b)   = " << norm(b) << "\n";
cout << "exp(b*pi) = " << exp(b*M_PI)  << "\n";  // check precision !
printf("\n");
printf("pi        = %50.48f\n",M_PI);

return 0;
}


# type conversion vs casting

• here: conversion of primitive data types and strings
• later: casting of objects
• typeid()  can be used also for classes
• to_string()  converts primitive data types to strings
• sprintf() : writing formatted data to string (array of char)
#include <iostream>
#include <stdio.h>
#include <typeinfo>    // typeinfo
using namespace std;

int main()
{
//                 implicit type conversion
short a=2000;
int b;
b=a;
printf("a = %5d,  b = %5d\n",a,b);
printf("\n");
//
//                 explicit type conversion
//
double x = 10.3;
int y,z;
y = int(x);    // functional notation
z = (int)x;    // c-like cast notation
printf("x = %6.3f,  y = %3d,  z = %3d\n",x,y,z);
printf("\n");
//
//                 type checking
//
if (typeid(a) != typeid(b))
{
cout << "a and b are of different types:\n";
cout << "a is: " << typeid(a).name() << '\n';
cout << "b is: " << typeid(b).name() << '\n';
}
//
//                 converting to strings using to_string
//
double myDouble = 0.3141;
printf("\n");
printf("number = %6.4f,  strResult = %s\n", myDouble,
to_string(myDouble).c_str());
//
//                 converting to strings via a string stream
//
int myInt = 123;
printf("\n");
char strResult[16];                               // string  (array of char)
sprintf(strResult, "%d %6.4f", myInt, myDouble);  // write to array of char
printf("number = %d,  strResult = %s\n", myInt, strResult);
//
//                 converting from strings
//
char text[] = "456";  // string to be converted
int intResult;        // number which will contain the result
sscanf (text,"%d",&intResult);        // pointer: &intResult
printf("  text = %s,  intResult = %d\n",text,intResult);
//
//                 ASCII character table
//
printf("\n");
printf("=== ===================== ===\n");
printf("=== ASCII character table ===\n");
printf("=== ===================== ===\n");
printf("\n");
for ( int x = 0; x < 128; x++ )
cout << x << ". "<< (char)x << "\n";
printf("\n");
//
return 0;
}


# arithmetic operators

• assignment and arithmetics
SymbolDescriptionExamples
=assignment int i=5;
+  -addition, subtraction int i=5+3; int i=5-3;
*  /multiplication, integer division int i=5*3; int i=9/3;
%modulo int i=14%3;
+  -unary plus/minus int i=+3; int i=-2;
+=  -=  *=   /=assignment and operation i += 5; // i = i + 5
++   --pre-/postfix increment/decrement i++; // i = i + 1

• naming of C++
• difference to ++C
#include <iostream>
using namespace std;

int main()
{
int myInt = 0;
cout << "0: myInt " << myInt   << endl;
//
++myInt;
cout << "1: myInt " << myInt   << endl;
//
myInt++;
cout << "2: myInt " << myInt   << endl;
//
cout << "3: myInt " << ++myInt << endl;
//
cout << "4: myInt " << myInt++ << endl;
cout << "5: myInt " << myInt   << endl;
//
return 0;
}


# mathematical functions

#include <iostream>
#include <math.h>
using namespace std;

int main()
{
double number,dsqrt,dpow,dlog,dlog10,expLog;

cout << "Please enter a number \n";
cin >> number;

dsqrt  = sqrt(number);
dpow   = pow(number,3);
dlog   = log(number);
dlog10 = log10(number);
expLog = log(exp(number));

cout << "\n";
cout << "square root of  " << number << "   is : "
<< dsqrt << "\n";
cout << "        log of  " << number << "   is : "
<< dlog << "\n";
cout << "      log10 of  " << number << "   is : "
<< dlog10 << "\n";
cout << "                " << number << "^3 is : "
<< dpow << "\n";
cout << " exp of log of  " << number << "   is : "
<< expLog << "\n";

return 0;
}


# arrays

• array length is fixed for all C++ versions below C++14
• 10-component integer array
int intArray[10];

• setting/assessing value of array-component k
intArray[k] = 4;             // setting
int b = intArray[k];         // assessing

• array with predefined values
int intArray[3] = {1, 2, 3};
double doubleArray[] = {1.0, 2.0, 3.0};  // [] may be left empty when initializing

• length n of array
note however myString.length() for strings
int n = sizeof(doubleArray) / sizeof(doubleArray[0]);

• multi-dimensional arrays: nxm matrix
int intMatrix[n][m];


# example: arrays

• arrays start always with [0]
• use const int for defining the array length
• C++ doesn't have any built-in reflective support;
e.g. for finding the name of a variable
• C++ does not (!) check array boundaries! Alwasy use
assert() for doing it by hand, turning off
assert() by compling with
g++ -DNDEBUG for production runs
• note: string is an object (class, see later),
that contains a buffer for small strings (to be placed on stack);
for sizeof(clase) see later
/* compile with  g++             -o test.e test.c  */
/*      or with  g++    -DNDEBUG -o test.e test.c  */
/*                      (turns assert()' off)     */
//
#include <iostream>         // input/output handling
#include <stdio.h>          // for formatted input/output
#include <assert.h>         // (assert()' calls abort if arg not true)
#define VARIABLE_NAME(x) #x     // a C++ macro definition
using namespace std;

int main()
{
const int arrayLength = 10;   // array length need to be constant
int goodHabit[arrayLength];   // much better programming
//
cout << "goodHabit has " << sizeof(goodHabit) / sizeof(goodHabit[0])
<< " elements\n\n";
//
goodHabit[0] = 0;                 // first element
for (int i=1;i<arrayLength;i++)   // starting at second element
goodHabit[i] = goodHabit[i-1]+1;
for (int i=0;i<arrayLength;i++)
cout << VARIABLE_NAME(goodHabit)
<< "[" << i << "] = "
<< goodHabit[i] << "\n";
printf("=== ==================== ===\n");
printf("=== array bound checking ===\n");
printf("=== ==================== ===\n");
string stringArray[] = {"apple","banana","oranges"};
for (int i=0;i<6;i++)
{
assert(i>=0);     // array size checking by hand
assert(i<sizeof(stringArray)/sizeof(string));
printf("stringArray[%d] = %s\n",i,stringArray[i].c_str());
}
return 0;
}


# example: matrices

• "Schiffe Versenken": Darstellung"
#include <iostream>  // input/output handling
#include <stdio.h>   // for formatted input/output
using namespace std;

const int X=9;
const int Y=7;

int main()
{
char Spielfeld[Y][X];
int x, y;
char cx, cy;
for (x=0; x<X; x++)
for (y=0; y<Y; y++)
Spielfeld[y][x] = '.';
//
// Anzeige und Eingabe
//
bool SchleifenEnde=false;
int xin, yin;
do {
printf("  ");
for (x=0; x<X; x++)
printf("%3d",x+1);
printf("\n");
//
for (y=0; y<Y; y++)
{
cout << (char)('A'+y) << " ";
for (x=0; x<X; x++)
printf("%3c",Spielfeld[y][x]);
cout << endl;
}
//
cout << "your hit: ";
cin >> cy >> cx;
xin = cx - '1';
yin = cy - 'A';
if (xin>=0 && xin<X && yin>=0 && yin<Y)
{
Spielfeld[yin][xin] = 'x';
cout << "# (yin,xin): (" << yin
<< "," << xin
<< ")\n\n";
}
else
SchleifenEnde = true;
} while (!SchleifenEnde);
}


# example: strings

• strings are classes containing member functions
which can be accessed by the . operator
#include <iostream>
using namespace std;

int main() {
string str1 = "To be or not to be, that is the question";
string str2 = "only ";
string str3 = str1.substr(6, 12);
//                    // endl == end of line
cout << "str1        :: " << str1 << endl;
cout << "str2        :: " << str2 << endl;
cout << "str3        :: " << str3 << endl;
cout << "str2 + str3 :: " << str2+str3 << endl;
//
cout << "str1 (again)         :: " << str1 << endl;
str1.insert(32, str2);
cout << "str1 (after insert)  :: " << str1 << endl;
str1.replace(str1.find("to be", 0), 5, "to jump");
cout << "str1 (after replace) :: " << str1 << endl;
str1.erase(9, 4);
cout << "str1 (after erase)   :: " << str1 << endl;
//
for (int i = 0; i < str3.length(); i++) // accessing the length
cout << str3[i];
cout << endl;
//
cout << "str3 (again)         :: " << str3 << endl;
cout << "str3.length()        :: " << str3.length() << endl;
str3.clear();
cout << "str3 (after clear)   :: " << str3 << endl;
}