Download Type Casting-Computing and Statistical Data Analysis-Lecture 03 Slides-Physics and more Slides Computational and Statistical Data Analysis in PDF only on Docsity!
Computing and Statistical Data Analysis
Lecture 3
Type casting: static_cast, etc.
Basic mathematical functions
More i/o: formatting tricks
Scope, namspaces
Functions
Type casting
Often we need to interpret the value of a variable of one type
as being of a different type, e.g., we may want to carry out
floating-point division using variables of type int.
Suppose we have: int n, m; n = 5; m = 3; and we want
to know the real-valued ratio of n/m (i.e. not truncated). We
need to “type cast” n and m from int to double (or float):
double x = static_cast(n) / static_cast(m);
will give x = 1.666666...
Similarly we can use static_cast(x) to turn a float
or double into an int, etc.
Will also work here with static_cast(n)/m;
but static_cast(n/m); gives 1.0.
Digression #2: value of an assignment and == vs. =
In C++, an assignment statement has an associated value,
equal to the value assigned to the left-hand side. We may see:
int x, y; x = y = 0;
Recall = is the assignment operator, e.g., x = 3;
== is used in boolean expressions, e.g., if ( x == 3 ) { ...
This says first assign 0 to y, then assign its value ( 0 ) to x.
This can lead to very confusing code. Or worse:
if ( x = 0 ) { ... // condition always false!
Here what the author probably meant was
if ( x == 0 ) { ...
Standard mathematical functions
Simple mathematical functions are available through the
standard C library cmath (previously math.h), including:
abs acos asin atan atan2 cos cosh exp fabs fmod log log10 pow sin sinh sqrt tan tanh
Most of these can be used with float or double arguments;
return value is then of same type.
Raising to a power, z = x
y
, with z = pow(x,y) involves log and
exponentiation operations; not very efficient for z = 2, 3 , etc.
Some advocate e.g. double xSquared = x*x;
To use these functions we need: #include
Google for C++ cmath or see www.cplusplus.com for more info.
Running testMath
Compile and link: g++ -o testMath testMath.cc
The numbers don’t line up in neat columns -- more later.
Run the program: ./testMath
Often it is useful to save output directly to a file. Unix allows
us to redirect the output:
./testMath > outputFile.txt
Similarly, use >> to append file, >! to insist on overwriting.
These tricks work with any Unix commands, e.g., ls, grep, ...
Improved i/o: formatting tricks
Often it’s convenient to control the formatting of numbers.
cout.setf(ios::fixed); cout.precision(4);
will result in 4 places always to the right of the decimal point.
cout.setf(ios::scientific);
will give scientific notation, e.g., 3.4516e+05. To undo this,
use cout.unsetf(ios::scientific);
cout.width(15) will cause next item sent to cout to occupy
15 spaces, e.g.,
cout.width(5); cout << x; cout.width(10); cout << y; cout.width(10); cout << z << endl;
To use cout.width need #include .
Scope basics
The scope of a variable is that region of the program in which it
can be used.
If a block of code is enclosed in braces { }, then this delimits
the scope for variables declared inside the braces. This
includes braces used for loops and if structures:
int x = 5; for (int i=0; i<n; i++){ int y = i + 3; x = x + y; } cout << "x = " << x << endl; // OK cout << "y = " << y << endl; // BUG -- y out of scope cout << "i = " << i << endl; // BUG -- i out of scope
Variables declared outside any function, including main, have
‘global scope’. They can be used anywhere in the program.
More scope
int x = 5; { double x = 3.7; cout << "x = " << x << endl; // will print x = 3. } cout << "x = " << x << endl; // will print x = 5
The meaning of a variable can be redefined in a limited ‘local
scope’:
In general try to keep the scope of variables as local as possible.
This minimizes the chance of clashes with other variables to
which you might try to assign the same name.
(This is bad style; example is only to illustrate local scope.)
The std namespace
C++ provides automatically a namespace called std.
It contains all identifiers used in the standard C++ library (lots!),
including, e.g., cin, cout, endl, ...
To use, e.g., cout, endl, we can say:
using std::cout; using std::endl; int main(){ cout << "Hello" << endl; ...
or we can omit using and say
int main(){ std::cout << "Hello" << std::endl; ...
using namespace std;
Or we can simply say
using namespace std; int main(){ cout << "Hello" << endl; ...
Although I do this in the lecture notes to keep them compact,
it is not a good idea in real code. The namespace std contains
thousands of identifiers and you run the risk of a name clash.
This construction can also be used with user-defined namespaces:
using namespace aNameSpace; int main(){ cout << x << endl; // uses aNameSpace::x ...
The usefulness of functions
Now we can ‘call’ ellipseArea whenever we need the area of
an ellipse; this is modular programming.
The user doesn’t need to know about the internal workings of
the function, only that it returns the right result.
‘Procedural abstraction’ means that the implementation details
of a function are hidden in its definition, and needn’t concern
the user of the function.
A well written function can be re-used in other parts of the
program and in other programs.
Functions allow large programs to be developed by teams
(as is true for classes, which we will see soon).
Declaring functions
Before we can use a function, we need to declare it at the top of
the file (before int main()).
double ellipseArea(double, double);
This is called the ‘prototype’ of the function. It begins with
the function’s ‘return type’. The function can be used in an
expression like a variable of this type.
The prototype must also specify the types of the arguments, in
the correct sequence. Variable names are optional in the
prototype.
The specification of the types and order of the arguments is
called the function’s signature.
Return type of a function
double ellipseArea(double, double);
The prototype must also indicate the return type of the function,
e.g., int, float, double, char, bool.
When calling the function, it must be used in the same manner
as an expression of the corresponding return type, e.g.,
The function’s return statement must return a value of this type.
double ellipseArea(double a, double b){ return PIab; } double volume = ellipseArea(a, b) * height;
Return type void
The return type may be ‘void’, in which case there is no return
statement in the function (like a FORTRAN subroutine):
void showProduct(double a, double b){ cout << "ab = " << ab << endl; }
To call a function with return type void, we simply write its
name with any arguments followed by a semicolon:
showProduct(3, 7);