Division of integers in C++ not working as expected - c++

I'm new here so really sorry if this is to basic but what am I missing here? This is just a dummy code:
#include <iostream>
using namespace std;
int main() {
unsigned int a, b, c;
int d;
a = 10E06;
b = 25E06;
c = 4096;
d = (a - b)/c;
std::cout << d << std::endl;
return 0;
}
cout is printing 1044913 instead of -3662. If I cast a and b to long the problem is solved. Is there a problem of overflow or something?

That's because (a-b) itself is unsigned:
#include <iostream>
using namespace std;
int main() {
unsigned int a, b, c;
int d;
a = 10E06;
b = 25E06;
c = 4096;
d = (a - b)/c;
std::cout << (a-b) << std::endl; // 4279967296
std::cout << d << std::endl; // 1044913
return 0;
}
The conversion from unsigned to int happens when d is assigned to, not before.
So (a-b)/c must be unsigned since a,b,c are.

Operations between unsigned numbers yield unsigned numbers. It's up to you to make sure the operations make sense, or protect against the opposite.
If you have unsigned int a = 2, b = 3;, what do you think the value of a-b would be?

Since a b and c are all declared as unsigned, the output of the computation (a-b)/c will be unsigned. Since the calculation of the values you provided cannot be properly represented with an unsigned type, things get a little messy. The unsigned value is then assigned to d, and even though this is signed, the value is already garbled.
I will also note that the notation 10E06 represents a floating point number that is then being implicitly cast to an unsigned int. Depending on the particular floating point value provided, this may or may not cast as expected.

You want your result to take a sign. So you should declare your variables as signed int or just int. That will give the desired result. If you cast a and b to long, a-b will be long and hence take a sign. Following is a solution.
int main() {
int a, b, c;
int d;
a = 10E06;
b = 25E06;
c = 4096;
d = (a - b)/c;
std::cout << d << std::endl;
return 0;
}
If you also want rational numbers you should use doubles or float (atlhough it won't give a different result for this particular case).
int main() {
double a, b, c;
double d;
a = 10E06;
b = 25E06;
c = 4096;
d = (a - b)/c;
std::cout << d << std::endl;
return 0;
}

Because of the way C++ (and many other C-based languages) deal with operators, when unsigned numbers are put into an expression, that expression returns an unsigned value, and not held in a mysterious inter-type state that might be expected.
Step-by-step:
(a - b) subtracts 25E06 from 10E06, which would normally return -15E06, is unsigned, so it's wrapped around to a whole bunch of junk.
This junk is then divided by c, and both inputs are unsigned, so the output is also unsigned.
Lastly, this is stuffed into a signed int, remaining at 1044913.
"unsigned int" is a type just like float and bool, even though it requires two keywords. If you want it to turn into a signed int for that calculation, you must either make sure a, b, and c are all signed (remove the unsigned keyword), or cast them as such when putting them into the expression, like this: d = ((signed)a - (signed)b) / (signed)c;

Related

C++ Data Type Range

I am trying to do a division of :-
#include <bits/stdc++.h>
using namespace std;
int main(){
int A = -2147483648;
int B = -1;
int C = A/B;
// this is not working
cout<<C<<endl;
// nor this is working
cout<<A/B<<endl;
// But this is working
cout<<-2147483648/-1<<endl; // printing the result 2147483648;
}
I am confused why this happening. Please explain.
Assuming the int type is 32-bits and uses two's complement representation, the first two cases exhibit undefined behavior because both -2147483648 and -1 fit in a int but 2147483648 does not.
In the third case, the expression -2147483648/-1 contains the integer literal 2147483648 (before being negated), and has the first type in which the value can fit. In this case, that would be long int. The rest of the calculation keeps the type, so no undefined behavior occurs.
You can change the data type to long long.
long long A = -2147483648;
long long B = -1;
long long C = A/B;
If your you need fractional result, try 'double' instead of 'long long'.

Converting a double to intptr_t in C++

Assume the following:
#include <iostream>
int main()
{
double a = 5.6;
intptr_t b = (intptr_t) a;
double c = (double) b;
return 0;
}
c will be 5. My question is, since intptr_t is also 64 bits on a 64 bit machine (same as double), how come the precision bits are not saved during casting?
Although intptr_t is meant to represent a pointer to an int, its underling type is still an integer. Thus
intptr_t b = (intptr_t)a
Is still truncating the double, similar to if you'd just written:
int b = (int)a;
What you want to do is take the address of a:
intptr_t b = (intptr_t)&a
And then convert it back
double c = *(double*)b;

How significant is (int) within a statement?

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

Why int8 works like char (C++) (Visual Studio 2015)

I'm trying to find the smallest int type in C++. I read that there are no types which use less than a byte, because is the minimum addressable size. The smallest one I found is int8_t, or _int8 visual studio type. I tried to use both, but the program stores the values as chars. There are a way to use this types as integers? Or even, if there are a way to use smaller types (2 bits (signed) would be perfect XD, I need to store only -1, 0 and 1), or any other numeric byte type.
Thanks in advance
The standard gives you the following types:
signed char
unsigned char
(with char being equivalent to one of these)
And your fixed-width int8_t, uint8_t on an 8-bit system are simply aliases for these.
They are all integers already.
Your statement "but the program stores the values as chars" suggests a misunderstanding of what values with these types fundamentally are. This may be due to the following.
The only "problem" you may encounter is the special-case formatting for these types in the IOStreams sublibrary:
const char c = 40;
std::cout << c << '\n';
// Output: "("
Since int8_t is/may be signed char, this is literally the same:
const int8_t c = 40;
std::cout << c << '\n';
// Output: "("
But this is easily "fixable" with a little integral promotion:
const char c = 40;
std::cout << +c << '\n';
// Output: 40
Now the stream gets an int, and lexically-casts it as part of its formatting routine.
This has to do with the type system and the function overloads provided by the standard library; it has nothing to do with "how the values are stored". They are all integers.
I tried to use both, but the program stores the values as chars.
It doesn't (store the values as chars). In C++, a char value is an integer value. The difference to other integer types, is in two places:
the compiler converts char literals to integers transparently
the standard library treats char type separately from other integer types (that is, it considers char to represent letters text characters, not numbers).
As far as the compiler is concerned, the code:
char x = 'A';
is equivalent to:
char x = 65; // set value to 65 (ASCII code for letter "A")
If you look in the debugger at the second definition of x, is probable the debugger/IDE will tell you x is 'A'.
Or even, if there are a way to use smaller types (2 bits (signed) would be perfect XD, I need to store only -1, 0 and 1), or any other numeric byte type.
There is no integer type with a smaller than 8 bits representation.
That said, you can (and probably should) create a custom type for it:
enum class your_type: std::uint8_t
{
negative = -1,
neutral = 0,
positive = 1
};
Choose values that make sense in the context of your program (i.e. not "negative, neutral and positive").
You can use a bit field with two bits.
With MSVC you could use #pragma pack(1) and structs to obtain this.
#pragma pack(1)
struct int2 {
int value:2;
};
#pragma pack()
int main()
{
int2 a;
for (int i = 0; i < 10; i++)
{
a.value = i;
std::cout << a.value << std::endl;
}
return 0;
}
Output:
0
1
-2
-1
0
1
-2
-1
0
1
I guess building constructors and operator functions to access the value indirectly shouldn't be a problem.
EDIT: Improved version with operators:
#pragma pack(1)
template <typename INT_TYPE, int BYTE_SIZE>
class int_x {
INT_TYPE value: BYTE_SIZE;
public:
int_x() :value(0) {}
int_x(INT_TYPE v) :value(v) {}
operator INT_TYPE() const {
return value;
}
int_x& operator=(INT_TYPE v) {
value = v; return *this;
}
int_x& operator+=(INT_TYPE v) {
value += v; return *this;
}
int_x& operator-=(INT_TYPE v) {
value -= v; return *this;
}
int_x& operator/=(INT_TYPE v) {
value /= v; return *this;
}
int_x& operator*=(INT_TYPE v) {
value *= v; return *this;
}
};
typedef int_x<int, 1> int1; //Range [-1;0]
typedef int_x<unsigned int, 1> uint1; //Range [0;1]
typedef int_x<int, 2> int2; //Range [-2;1]
typedef int_x<unsigned int, 2> uint2; //Range [0;3]
typedef int_x<int, 3> int3; //Range [-4;3]
typedef int_x<unsigned int, 3> uint3; //Range [0;8]
#pragma pack()

Having trouble with return values for user-defined Functions

I'm doing a simple Pythagorean function
User inputs two numbers, both numbers are shipped off to a user-defined function called Hypo, and hypo's supposed to return one value, C, which is the answer.
Here's my script.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int hypo(double a, double b);
int main(void)
{
double one, two;
//user inputs two variables
scanf("%lf %lf", &one, &two );
printf("Your C number is: %.2lf\n", hypo(one, two));
system("PAUSE");
return 0;
}
/*-------------------------------------------------------------------------*/
int hypo(double a, double b)
{
double c;
c = sqrt((a*a)+(b*b));
printf("Currently, A = %.2lf, and B = %.2lf, C = %.2lf\n", a, b, c);
return c;
}
On my computer, it works all the way until the end, Return c; which for some reason, returns the value 0 to the Main function. (I tested to see just where the error was, hence the printscreening in the hypo function.)
I want to understand this.
I'm pretty sure I have the synax wrong, or there's something I didn't read yet that's gone over my head, but after an hour of looking through books and checking youtube videos, I don't understand why this isn't working.
EDIT:
Thank you all for the fast replies! I changed it to a double, (realizing my mistake in the process too xD ) and it works like a charm now.
Very happy with how fast you guys all answered, I'll be sure to pass it forward :)
You need to change the return type to double:
double hypo(double a, double b)
{
double c;
c = sqrt((a*a)+(b*b));
printf("Currently, A = %.2lf, and B = %.2lf, C = %.2lf\n", a, b, c);
return c;
}
Your return type is int when you probably want double - small values will be casted and result in 0 (i.e. 0.5 is 0 when stored in int).
The exact reason why you are getting 0 is mismatched formatting - you use float formatting to print integer value. For printing integer use %d, but if you specify return type of hypo correctly (double) this problem will disappear.
You have defined your variable c as type double:
double c;
But you are trying to return an int:
int hypo(double a, double b);
You should either change the return type of hypo to double or cast c to int. However, casting will throw away any fractions (making 2.678 into 2):
return (int)c;
Therefore I recommend you change the return type to double instead, which is also more logical when trying to calculate the hypotenuse (which may contain fractional digits):
double hypo(double a, double b);
You have hypo returning an int, but you're using it as if it's a double. You should switch it to:
double hypo(double a, double b);
And, in the implementation:
double hypo(double a, double b)
{
double c;
// ...
When you return as an int, the resulting value c will get truncated to an int instead of displaying the full value. This will cause it to convert to 0 for anything positive number less than 1.0. Also, your format string is specifying a double, and you're passing an int, which will cause the display to always print the wrong answer.