C++ - Where in my code should I include static_cast? - c++

My static_cast does not seem to be working. I create 5 int variables at the beginning of my code and attempt to change one (the total) to a double after performing calculations on the other 4, but it keeps displaying the int.
#include <iostream>
#include <iomanip>
#include <cstdlib>
using namespace std;
int main ()
{
int grade1, grade2, grade3, grade4, avg;
cout << "Please input four grades: " << endl;
cin >> grade1;
cin >> grade2;
cin >> grade3;
cin >> grade4;
avg = (grade1 + grade2 + grade3 + grade4) / 4;
cout << "Grades: " << grade1 << ", " << grade2 << ", " << grade3 << ", " << grade4 << endl;
cout << "\n";
cout << "Average grade: " << static_cast<double>(avg) << endl;
return 0;
}

When you are combining the integers and assigning them to avg.
You already have integer rounding conversion, so you need to static cast before you assign the number to the avg result.
You also don't even need to use static cast as long as you divide by 4.0 and make avg a double.
Example:
double avg = static_cast<double>(grade1+grade2+grade3+grade4) / 4.0;
// Alternative without static that still works
double avg = (grade1+grade2+grade3+grade4) / 4.0;

I would suggest that the literal answer to your question "Where in my code should I include static_cast?" is quite simple: nowhere, if at all possible.
static_cast - like all the C++ _cast operators, and all explicit (C-style) typecasts should be avoided wherever possible. They have their uses, but it is better to minimise their usage, and certainly to avoid using them as blunt instruments to fix problems in code.
In your case, the correct results can be obtained quite simply by using appropriate types of variables, and any literal values having a suitable type.
Firstly, avg needs to be of type double. This involves changing
int grade1, grade2, grade3, grade4, avg;
to
int grade1, grade2, grade3, grade4;
double avg;
Second, the calculation of the value of avg needs to be changed so it doesn't do an integer division. This means changing
avg = (grade1 + grade2 + grade3 + grade4) / 4;
(which doesn't work because grade1, ... grade4 are all of type int, their sum is an int, the literal 4 is an int, and dividing two ints produces an int) to
avg = (grade1 + grade2 + grade3 + grade4) / 4.0; // note the 4.0
This works, because the literal 4.0 has type double. The value (grade1 + grade2 + grade3 + grade4) is calculated as an int but, because it is being divided by a double, that integral value is converted implicitly to double before performing the division - and the result is of type double.
This is the only place in which I would consider using a static_cast here, by converting the 4 to a double.
avg = (grade1 + grade2 + grade3 + grade4) / static_cast<double>(4);
which has the same net effect as the previous calculation of avg. In your code, it makes little difference. But a static_cast can be useful here in more general-purpose code, for example, if the number of input values (grade1, grade2, etc) is calculated as an integral value (e.g. the number of elements in an array).
The third thing you can do is remove the static_cast from the statement that outputs avg since it is now redundant (converting a double to double has no effect). In other words turn
cout << "Average grade: " << static_cast<double>(avg) << endl;
to
cout << "Average grade: " << avg << endl;

There are two issues in your code.
The first is that you declared avg as int, so the result is going to be rounded as int always.
However, declaring avg as double will not solve your problem immediately. In C++, operators are executed on objects of the same type and the result is an object of the same type.
(grade1 + grade2 + grade3 + grade4) is an int and 4 is an int, therefore the result will be an int. It doesn't matter if later is implicitly or explicitly casted to double, you will still get a rounded result.
In case the operands are not the same type, the compiler will implicitly promote one to match the other. The following lines will give you the correct result:
static_cast<double>(grade1 + grade2 + grade3 + grade4) / 4;
(grade1 + grade2 + grade3 + grade4) / 4.0;
static_cast<double>(grade1 + grade2 + grade3 + grade4) / 4.0;

An int cannot hold decimal places. int / results in an int, there are no decimals that result. You need to use the correct /, i.e at least one of the operands must be double to get a double result.
#include <iostream>
int main () {
std::cout<<"Please input four grades: "<<std::endl;
int grade1, grade2, grade3, grade4;
std::cin>>grade1;
std::cin>>grade2;
std::cin>>grade3;
std::cin>>grade4;
double avg=static_cast<double>(grade1+grade2+grade3+grade4)/4;
std::cout<<"Grades: "<<grade1<<", "<<grade2<<", "<<grade3<<", "<<grade4<<std::endl<<std::endl;
std::cout<<"Average grade: "<<avg<<std::endl;
}
You don't need the static cast here, as you can change the int literal 4 to a double literal 4.0, but if you are summing the elements of a vector then calling size() on it, that will be an integer, and you will have to cast somewhere.

Related

double, float, {0.0}, {0.0f}, what's the big deal?

So I wrote this small practice program that tells you how many nickels and cents you would need for the amount given. I don't undersand why the program outputs 0 for cents even the the math is correct. I can't seam to understand what the issue is.
// Example program
#include <iostream>
using namespace std;
int main()
{
const double nickels{0.05};
const double cents{0.01};
int amt_needed_nickels{0}, amt_needed_cents{0};
double amt_val{0.06f}; // for 0.06 cents
double amt_val_copy{amt_val};
amt_needed_nickels = amt_val / nickels;
if(amt_needed_nickels != 0)
amt_val -= (nickels * amt_needed_nickels);
amt_needed_cents = amt_val / cents;
cout << "If it costs $" << amt_val_copy << ", you'll need:\nNickels: " << amt_needed_nickels << "\nCents: " << amt_needed_cents << "\n";
cout << "Even though amt_val is " << amt_val << ", and cents is also " << cents << ", and 0.01/0.01 does equal 1, why is amt_needed_cents not 1?\n";
}
To be fair I know if i change the const double cents{0.01} to const float cents{0.01}, and remove the f from double amt_val{0.06f}; to double amt_val{0.06}; it will work, but i fail to understand what's really going on beneath the surface. Why does the program give 0 to amt_needed_cents above, and 1 in the other cenario?
// Example program
#include <iostream>
using namespace std;
int main()
{
const double nickels{0.05};
const float cents{0.01};
int amt_needed_nickels{0}, amt_needed_cents{0};
double amt_val{0.06}; // for 0.06 cents
double amt_val_copy{amt_val};
amt_needed_nickels = amt_val / nickels;
if(amt_needed_nickels != 0)
amt_val -= (nickels * amt_needed_nickels);
amt_needed_cents = amt_val / cents;
cout << "If it costs $" << amt_val_copy << ", you'll need:\nNickels: " << amt_needed_nickels << "\nCents: " << amt_needed_cents << "\n";
cout << "I know this is correct, but I don't know what the compiler is thinking with this as compared to the other\n\n";
}
Floating point calculations are not precise, when doing math you get the very small difference, which will break your program if you try to check for an exact equality of the numbers. For example, 1.2 * 3 is not exactly 3.6 (note that this doesn't mean all calculations are inexact: e.g. multiplication by any power of 2 is always exact: things like 1.5 * 2 and 1.1 / 4 always give the best answer possible). This is because decimal fractions like 1/10 and 1/100 are not exactly representable in binary, which is an issue when our coins are based on 1/100 (the cent).
In your program, you should instead represent coins as an integers by converting all values to cents, then everything will work just fine. That is, you know that the largest denominator you will ever deal with is 100, so you may as well multiply everything by 100. So, nickels is going to be 5, cents is going to be 1 and all calculations will be precise.
To avoid any confusion, here's your code in integers:
int dollars = 100, nickels = 5, cents = 1;
int amt_needed_dollars = amt_val / dollars;
amt_val -= amt_needed_dollars * dollars;
int amt_needed_nickels = amt_val / nickels;
amt_val -= amt_needed_nickels * nickels;
// skipped dividing by cents, because it's '1' anyway
int amt_needed_cents = amt_val;
Float: A floating point number. It's a single-precision 32bit number. More common.
Double: Like the name it holds "double" the value of a float. It's a double-precision 64bit number. It's more precise and can hold way more decimal points.
I'm not the best with c++ but it looks like the problem is here:
int amt_needed_nickels{0}, amt_needed_cents{0};
amt_needed_nickels = amt_val / nickels;
Try changing amt_needed_cents to a float or double the parsing/rounding it later. Unlike other languages (like JS) c++ is annoying when trying to convert types like that. You are dividing two floats to an int which probably truncates the decimal.

C++ multiply float by fraction

just started C++ from a MATLAB background and getting confused.
float farenheit, celcius;
cin >> farenheit;
celcius = (farenheit - 32) * (5 / 9);
cout << "Temperature (c): " << celcius;
why does multiplying by 5/9 not work as expected, but this does?:
float farenheit, celcius;
cin >> farenheit;
celcius = ((farenheit - 32) * 5) / 9);
cout << "Temperature (c): " << celcius;
Thanks!
Thanks everyone,
C++ interprets 5 and 9 as int values so 5/9 is also an int.
5/9 = 0.566 which is truncated down to 0.
To fix this, append .0 or .f to the values be interpreted as a double or float respectively.
C++ considers 5 and 9 to be integers and the division is integer division, which means 5/9 = 0 (it returns the quotient).
So use 5.0 and 9.0 if you want them to be floating points.

how to avoid the loss of precision when trying to round number? (C++)

just finished my first week of C++(using Visual Studio 2017), I wrote a program that asks the user for the amount of money and will print the number of bills and coins. it works at the beginning, but sometimes it just prints wrong number.(when the user input $1.28, it shows 1 dollar, 1 quarter and 2 pennies.)
here is my code, is there anything wrong? the algorithm or the data type?
#include<iostream>
using namespace std;
float Q = 0.25;
float D = 0.10;
float N = 0.05;
float P = 0.01;
float Dollar = 1;
float money;
float dollars, quarters, dimes, nickels, pennies;
int main() //to break money into coins.
{
cout << "how many money do u have?" << endl;
cin >> money;
dollars = (int)money;
quarters = (int)((money - dollars*Dollar)/Q);
dimes = (int)((money - dollars*Dollar - quarters*Q) / D);
nickels = (int)((money - dollars*Dollar - quarters*Q - dimes*D) / N);
pennies = (int)((money - dollars*Dollar - quarters*Q - dimes*D - nickels*N) / P);
cout << "$" << money << " can be break into :" << endl;
cout << dollars << " dollars. " << endl;
cout << quarters << " quarters. " << endl;
cout << dimes << " dimes. " << endl;
cout << nickels << " nickels. " << endl;
cout << pennies << " pennies. " << endl;
}
how to avoid the loss of precision when trying to round number? (C++)
When you convert from floating point to integer, the fractional part is truncated. To ensure no loss of integer precision (getting the right "whole"), add 0.5 to the result each time e.g:
quarters = static_cast<int>(((money - dollars*Dollar)/Q)+0.5);
This however doesn't work when the result is negative e.g:
50.5 - 100 = -49.5 -> +1 = -48.5 -> -48... not 49
For negatives you would want to therefore subtract 0.5.
I'd assume, that in the line
pennies = (int)((money - dollars*Dollar - quarters*Q - dimes*D - nickels*N) / P);
the part (money - dollars*Dollar - quarters*Q - dimes*D - nickels*N) will produce a value, that is not exactly .03, but a tad below. This is due to the nature of floating point arithmetic, you should read on that. Given that it's something like .029999999995, division by .01 will not yield 3.0, but maybe 2.9999999995. Since you are not rounding, but casting the value to an integer, the whole part after the period will be thrown away, hence it results in 2 pennies.
How can you solve this issue?
The simplest thing will be to round the value instead of casting it, this should yield the correct value, but this is kind of a hacky solution to an issue there is an exact solution for. You could also try to use double instead of a float, but this, too, would not solve the issue. You might get this correct, but the same a similar bug could still occur.
Store whole pennies
You could store the whole amount as an integer (whole pennies)
int amountInPennies;
int penniesPerDollar = 100;
int penniesPerQuarter = 25;
int penniesPerDime = 10;
int penniesPerNickle = 5;
int totalDollars = amountPennies / penniesPerDollar;
int totalQuarters = (amountPennies - totalDollars * penniesPerDollar) / penniesPerQuarter;
...
Decimal types
In a real world application dealing with money (well, depending on the type) you'd most likely go with some kind of decimal type instead of a float. According to this answer there are libraries with arbitrary precisions arithmetic available under the GNU license. You could still roll your own decimal type, that - more or less - does what I presented in the first approach. This might be a great excercise to learn, but maybe a ready-made library would be the better option when it comes to a real world application.

C++ numbers aren't rounding correctly

I am new to Stack Overflow, and programming in general. I am in a few classes for programming C++ and have come across an assignment I am having a bit of trouble with. This program is supposed to take fahrenheit and convert it to celsius. I have seen other programs, but could not find a duplicate to my particular problem. This is my code.
#include <iostream>
using namespace std;
int main()
{
int fahrenheit;
cout << "Please enter Fahrenheit degrees: ";
cin >> fahrenheit;
int celsius = 5.0 / 9 * (fahrenheit - 32.0);
cout << "Celsius: " << celsius << endl;
return 0;
}
So this is working great on 4 of the 5 tests that are run. It rounds 22.22 to 22 and 4.44 to 4 like it should, but when 0 F is put in, it rounds -17.77 to -17 instead of -18. I have been researching for about an hour and would love some help! Thank you.
Use std::round() instead of relying on the implicit conversion from double to int. Either that, or do not use conversion at all, show the temperature as a double.
EDIT: As others already pointed out, implicit conversion will not round but truncate the number instead (simply cut off everything after the decimal point).
Integers round down implicitly, as do casts to integer types.
Most likely, using a float in place of an int would give the most sane results:
#include <iostream>
using namespace std;
int main()
{
int fahrenheit;
cout << "Please enter Fahrenheit degrees: ";
cin >> fahrenheit;
float celsius = 5.0 / 9 * (fahrenheit - 32.0);
cout << "Celsius: " << celsius << endl;
return 0;
}
To get normal-looking output (fixed-point like "14.25", not scientific with e notation), pass std::fixed to cout before printing the floating point. You can also use cout.precision() to set the number of digits you would like in the output.
If for some other reason you need an int, use std::round() around the right hand of the expression.
When the compiler converts a floating point number to an integer, it doesn't round, it truncates. I.e. it simply cuts of the digits after the decimal point. So your program behaves as it is programmed to do.
int x = 3.99;
int y = std::round(3.99);
std::cout
<< "x = " << x << std::endl
<< "y = " << y << std::endl
;
-->
x = 3
y = 4
C/C++ is not doing floating point round when static_cast<int>-ing a float to an int. If you want to round, you need to call library function std::round()

Warning when converting to `int' from `double'

How do you get the return type to come back as a double for this expression: a = 2 * NUM + z;?
Here is my full program:
#include <iostream>
using namespace std;
int main()
{
const int NUM = 10;
const double x = 20.5;
int a, b;
double z;
char grade;
a = 25;
cout <<"a = " <<a <<endl;
cout <<" Enter two integers : ";
cin >> a >> b;
cout << endl;
cout << " The numbers you entered are "
<<a <<" and " <<b <<endl;
z = x + 2 * a - b;
cout <<"z = " <<z <<endl;
grade = 'A';
cout <<"Your grade is " <<grade <<endl;
a = 2 * NUM + z;
cout << "The value of a = " << a <<endl;
return 0;
}
Just declare a to be a double instead of an int.
double a;
int b;
// ...
You've defined a as an int so there's no way it can hold a double value. If you change the definition to double a; it should work fine.
Your z is a double so 2 * NUM + z is also a double, but you assigned the value to a which is an int. I'm not really what you are trying to do here; if you are trying to store the value of 2 * NUM + z in a with truncation, then you should add a cast: a = static_cast<int>(2 * NUM + z); OTOH, if you don't want truncation but want to store the full double value, then you need to store it in a double variable.
From the standard, 6.3.1.8 Usual arithmetic conversions
.......
Otherwise, the integer promotions are performed on both operands. Then the following rules are applied to the promoted operands:
If both operands have the same type, then no further conversion is needed.
Otherwise, if both operands have signed integer types or both have unsigned integer types, the operand with the type of lesser integer conversion rank is converted to the type of the operand with greater rank.
So, in the expression -
2 * NUM + z;
NUM is a of type const int which is of lower rank when compared to the type of z which is double. According to rule, int is promoted to double. The result of 2 double type operands will yield result of type double. But you are taking assigning the result to an int type, hence the warning. Changing the type of a to double should work fine.