If I have:
#include <iostream>
int main()
{
float a,b,c;
b = 7;
c = 2;
a = (int) (b / c);
std::cout << a;
}
Does (int) only affect the data type during cout so that 'a' can be printed as an integer or does it affect 'a' as a variable changing it to an 'int'?
Does (int) only affect the data type during cout so that a can be printed as an integer or does it affect a as a variable changing it to an int?
Neither.
a = (int)(....);
only changes what is assigned to a. In this case it truncates the floating point number and assigns the integral part of the number to a.
It does not change how a is processed in cout << a. You will notice a truncated value in the output. However, the reason for that is that a truncated value got assigned to a in the previous statement not because cout << a is processed differently.
It does not change the type of a to an int. The type of a variable cannot be changed in C++. It remains unchanged for the entire life of the program.
In this particular case it converts from a float value, the result of b/c into an int, then as a is still a float, converts it back to a float.
This is an easy, if sometimes problematic way of rounding something to an integer value.
Remember that in C++ variables never change their fundamental type. Something defined as a float stays a float forever. You can force other values into the same memory location, you can recast them, but the variable itself always has a fixed intrinsic type.
Cast does not change the type of a variable the casted value is assigned to.
In your case, result of b/c is casted (truncated) to an int, which is then promoted to float.
In this case the int is a cast datatype.
What the computer are thinking
Inside the main function:
float a, b, c;
Declaring 3 variables of data_Type float.
b = 7;
c = 5;
Assigned value of 7 to b and value 5 to c.
a = (int) (b / c);
A is equal to b/c ==> 7/5 ==> 1.4, wait, the programmer asked to cast the data as int so 1.4 ==> 1
std::cout << a;
Output: 1.0
Hope this help
Related
I am self teaching my self teaching myself C++
but I am having a trouble make a simple input/output calculator.
Here is what I have come up with:
#include <iostream>
using namespace std;
int main()
{
cout << "THIS IS TEST CALCULATOR!" << endl;
int fn,sn,dvi; //fn- FIRST NUMBER, sn - SECOND NUMBER
cout << "Please type in the first number: " << endl;
cin >> fn;
cout << "Please type in the second number: " << endl;
cin >> sn;
cout << "Please choose type ( type in one: division, multiplication, subtraction, addition or modulus): "<< endl; //Asks for the type on calculation; needs to type in one.
std::string tp;
cin>>tp;
dvi = (fn/sn); // division
if (tp == "division"){
cout<<fn<<" divide by "<<sn<<" is "<<dvi<< endl;
}
}
result:
8/6 = 1.333333... not 1
You are performing integer division, and therefore 8/6 is 1. If you want floating point arithmetic, you could change fn,sn and dvi to float instead of int, or you could simply cast one or both of the arguments to a float (or double).
See this question for more in-depth answers.
Since the decalred variable type is int you will always get the floor of number.
All three should be of type float or double. Else dvi can be of this type and typecast the fn and sn to same type (float/double) during division.
When dividing integers you get integer values not decimal ones. To solve your problem you either declare them float or double or cast the operation.
double dvi = ((double)fn / (double)sn); // division
Instead of declaring fn,sn,dvi as ints, you should declare them as doubles:
double fn,sn,dvi;
Otherwise, dividing integers by integers in C++ will truncate the numbers to a smaller whole number. For example: 5/3 would equal 1, even though in reality it equals 1.6667. C++ will not round up to 2.0, it will round down to 1.
Another workaround for this issue if you're not using variables is to add the decimal to whole numbers so that the compiler recognizes them as doubles. For example: 5.0/2.0 = 2.5
The problem in your code is that you are dividing 2 variables that are of type int, and storing it in a variable that is also of type int. All three variables:
fn
sn
dvi
are of type int in your code. An int variable only stores a whole integer number, ranging from positive infinity to negative infinity. This means that when you divide 2 numbers that do not produce an integer, the floating point value is rounded off so that it can be stored in the int variable, which in your case is dvi. In addition, even if dvi alone is of data type float, your division will still round to a whole number as you have divided two variables of data type int, namely fn and sn, and in c++, when two integers are divided, the end result is always rounded off regardless of the data type of the variable it will be stored in.
The easiest way to get around the problem is to change the declaration of these variables to:
double fn, sn, dvi;
NOTE: I use double here, as it can store a more precise value since it has 8 bytes allocated to it in contrast to 4 for a float.
This is the easiest way to get around your problem. Alternatively, we can use casting in the mathematical step of your code; in that case we would declare the variables as:
int fn, sn;
double dvi;
Then in the step where you divide the numbers, you can do the following:
dvi = (double)(fn/sn);
This is called casting; the compiler here is "forced" to treat the end result of this division as a double. In your case it will work, as you are dividing numbers, however, as a side note, it cannot be done in all cases (you cannot cast a string as a float for example). Here is a link if you want to learn more about casting:
Typecasting in C and C++
A third way, simpler than casting would be to do the following:
dvi = (fn/sn)*1.0;
This can be done only if dvi is of type float or double. Here, the mathematical operation involves a float, so all values are not of type int. As a result, the precision of the value is preserved with a decimal point, in your case, it will store 1.33333333333... instead of 1.
Sorry for the late reply, I couldn't get time to answer your question yesterday.
I have old pascal code
var i : longint;
m : double;
begin
.....
i := trunc(m);
I have to convert it to C++ code.
An obvious thing here is to write
double m;
int i;
.....
i = static_cast<int>(std::trunc(m));
But the problem here is than pascal's trunc returns integer
function trunc(
d: ValReal
):Int64;
while c++'s trunc returns double.
Is it possible that for example trunc(2.3) will return 1.999999999999
and static_cast will make it 1 instead of 2? If yes is it correct to use static_cast without trunc to get same pascal's behavior?
i = static_cast<int>(m);
When you convert a floating-point value to an integer value in C++, the floating-point value is truncated automatically.
Take a look at the following simple example:
#include <iostream>
int main()
{
double d = 12.98;
int i = d;
std::cout << "i = " << i << '\n';
}
The above program will print
i = 12
Conversions like these are done implicitly by the compiler. For more information please read about implicit conversions (specifically read about floating-integral conversions).
However, it's important to note (from the linked reference):
If the value cannot fit into the destination type, the behavior is undefined
So the floating point value, after truncation, must fit into the integer type on the left-hand side of the assignment.
All integers (and most longs?) are exactly representable in double. A function like trunc that's defined to return an integer in mathematical sense will never return something that's not an exact integer if its proper return value can be represented in double.
I have such code:
double x = 100.1;
double y;
int *p;
p = (int *) &x;
y = *p;
cout << "y value is: " << y << endl;
I understand that it's wrong and we get 4 bytes instead of our 8 bytes. I also know floating numbers have some tricky representation at memory (but don't know how), but this script gives me such output:
y value is: 1.71799e+09
As I understand it's also value with floating point. By my pointer is int and I also expect int result. Why it's not? What I should read to understand?
By my pointer is int and I also expect int result. Why it's not?
Because y is a double, not an int. Now, if you mean to ask why doesn't y have an integral value, since it should be the result of the conversion of an int (which must* have an integral value) to double, take a look at the output of the following:
std::cout << "y value is: " << std::fixed << y << '\n';
The output you should see is:
y value is: 1717986918.000000
So, y does have an integral value, you simply printed it out using scientific notation. And if you wonder why y has this particular integral value, it's because that's the value *p had.
std::cout << "*p is: " << *p << '\n';
*p is: 1717986918
If you were to look at a memory dump of x with the value of 100.1, you would see:
66 66 66 66 66 06 59 40
And when you access this as an int, you get 66 66 66 66, which, converted to decimal, is 1717986918.
One other thing to note is that none of this is guaranteed by C++. In fact your program is not actually legal, because you're violating the aliasing rules when you access the double x through a pointer to int. Your program could be made legal and get the same results, but C++ doesn't specify the representation of floating point values, so the particular integral value could legally be different.
What I should read to understand?
Here's an article that plays with the representation of floats: http://ridiculousfish.com/blog/posts/float.html
C++ doesn't specify how floats are represented, but most C++ implementations use IEEE-754, so you might also take a look at that specification. Here's the wikipedia page to start you on that: https://en.wikipedia.org/wiki/IEEE_floating_point
To learn about C++'s aliasing rules you can find and read the spec. strict aliasing is covered in ยง3.10/10, IIRC. There are also plenty of questions and answers about aliasing here on SO.
1.71799e+09 is the floating point representation of the integer 1,717,99x,xxx.
By my pointer is int and I also expect int result. Why it's not?
Your pointer is int *, and you are getting an int result.
But that's not what you're displaying. You're displaying y which is a double.
1.71799e+09 is the double representation of the int you got.
When you do
y = *p;
The variable y takes the int pointed to by p, and then converts it to a double.
Suppose sizeof(double) is 8 and sizeof(int) is 4
Doing x = 100; you put the double value 100 in x on 8 bytes. Then when you do y = *p; you would only use 4 of the 8 bytes, as an int value, then convert that number to a double.
The binary format of a double and of an int are different. E.g. 100 as double is not represented the same way as 100 int (let alone the size difference, e.g. 8 vs 4).
See this link
double x = 100.1;
double y;
int *p;
p = (int *) &x;
// Set a pointer of type integer to point at a floating point. Better C++ style
// would be p = reinterpret_cast<int *>(&x);
// which explains more clearly what you are doing - reinterpreting the pointer as
// a different type.
y = *p;
// *p is an integer. So y is set to the value of *p, which is some crazy
// integer value formed from the interpretation of a double as integer.
cout << "y value is: " << y << endl;
See comments in the code above. You are making a pointer point to data of a different type, then wondering why the binary digits transformed don't represent what it originally represented...
(Technically, this code is in violation of the rules about aliasing - basically, you are using the same piece of memory for two different purposes, and the compiler is not obliged to "do the right thing" in this case - I suspect it does something of what you can expect in this particular case - if what you expect is that you get an integer value represented by the four first bytes of a double, that is).
If you want y to actually contain the integer representation of the number in x, you want:
y = (int)x;
There is no sensible way we can use a pointer to do this conversion.
You're triggering undefined behavoir when you run the following line:
p = (int *) &x;
Once you've triggered undefined behavoir the rest of your question is fairly pointless as reasoning about undefined behavoir doesn't make sense (although looking at the rest of your question, it may be that this bit of undefined behavoir doesn't affect what you're really asking. I'm not sure though.)
Read C++ pointers and data types documentation
http://www.cplusplus.com/doc/tutorial/pointers/
http://www.cplusplus.com/doc/tutorial/variables/
OK so I tried doing this
int b;
char x = 'a';
//Case 1
b = static_cast<int>(x);
std::cout<<"B is : "<<b<<std::endl;
//Case 2
b = *(int*)&x;
std::cout<<"B is changed as :: "<< b <<std::endl;
Now I know that in case 2, first byte of x is reinterpreted to think that it is an integer and the bit pattern is copied into b which gives of some garbage and in case 1 it just converts the value from char to int.
Apart from that are there any differences between these two?
The first one just converts the value: int b = x; is the same as int b = static_cast<int>(x);.
The second case pretends that there is an int living at the place where in actual fact the x lives, and then tries to read that int. That's outright undefined behaviour. (For example, an int might occupy more space than a char, or it might be that the char lives at an address where no int can ever live.)
The 2nd case is a C-style cast (as identified by bhuang3), but it's not the C-style equivalent to case 1. That would be
b = (int)x;. And the C++ equivalent of case 2 would be b = *reinterpret_cast<int*>(&x); Either way you do it, case 2 is undefined behavior, because x occupies one byte, while forcibly reading an int's worth of data at x's address will either give you a segmentation fault (bus error on some systems) if it's not at a legal address for an int, or it will just read the next 3 bytes, whose values we don't know what they are. Thus it reads "garbage" as you observed.
The static_cast doesn't provide runtime checks, which is used if you know that you refer to an object of a specific type.
The seconde case actually is c-style cast
define a float variable a, convert a to float & and int &, what does this mean? After the converting , a is a reference of itself? And why the two result is different?
#include <iostream>
using namespace std;
int
main(void)
{
float a = 1.0;
cout << (float &)a <<endl;
cout << (int &)a << endl;
return 0;
}
thinkpad ~ # ./a.out
1
1065353216
cout << (float &)a <<endl;
cout << (int &)a << endl;
The first one treats the bits in a like it's a float. The second one treats the bits in a like it's an int. The bits for float 1.0 just happen to be the bits for integer 1065353216.
It's basically the equivalent of:
float a = 1.0;
int* b = (int*) &a;
cout << a << endl;
cout << *b << endl;
(int &) a casts a to a reference to an integer. In other words, an integer reference to a. (Which, as I said, treats the contents of a as an integer.)
Edit: I'm looking around now to see if this is valid. I suspect that it's not. It's depends on the type being less than or equal to the actual size.
It means undefined behavior:-).
Seriously, it is a form of type punning. a is a float, but a is also a block of memory (typically four bytes) with bits in it. (float&)a means to treat that block of memory as if it were a float (in other words, what it actually is); (int&)a means to treat it as an int. Formally, accessing an object (such as a) through an lvalue expression with a type other than the actual type of the object is undefined behavior, unless the type is a character type. Practically, if the two types have the same size, I would expect the results to be a reinterpretation of the bit pattern.
In the case of a float, the bit pattern contains bits for the sign, an exponent and a mantissa. Typically, the exponent will use some excess-n notation, and only 0.0 will have 0 as an exponent. (Some representations, including the one used on PCs, will not store the high order bit of the mantissa, since in a normalized form in base 2, it must always be 1. In such cases, the stored mantissa for 1.0 will have all bits 0.) Also typically (and I don't know of any exceptions here), the exponent will be stored in the high order bits. The result is when you "type pun" a floating point value to a an integer of the same size, the value will be fairly large, regardless of the floating point value.
The values are different because interpreting a float as an int & (reference to int) throws the doors wide open. a is not an int, so pretty much anything could actually happen when you do that. As it happens, looking at that float like it's an int gives you 1065353216, but depending on the underlying machine architecture it could be 42 or an elephant in a pink tutu or even crash.
Note that this is not the same as casting to an int, which understands how to convert from float to int. Casting to int & just looks at bits in memory without understanding what the original meaning is.