This question already has answers here:
Is subtracting larger unsigned value from smaller in C++ undefined behaviour?
(2 answers)
Closed 3 years ago.
In C++ the compiler reminds me that subtracting unsigned values is unsigned and so calling abs() is pointless:
uint64_t a, b;
if (std::abs(a - b) > 10) {
std::cout << "Divergence achieved!" << std::endl;
}
OK, I understand that subtraction is addition, and I know in my instance that the numbers will be less than 2^63, so I static_cast to int64_t. But the point of calling abs was to avoid writing
if (a - b > 10 || b - a > 10) {
std::cout << "Divergence achieved!" << std::endl;
}
Is there a more idiomatic way to do this?
You can use std::minmax so you don't have to repeat the condition. This will give you a reference to the minimum and maximum values so you can always do the subtraction in the right direction. That would look like
uint64_t a, b;
auto minmax = std::minmax(a,b);
if (minmax.second - minmax.first > 10) {
std::cout << "Divergence achieved!" << std::endl;
}
Computers always subtract integers the same way - in a binary form. The assignment of signed or unsigned is an instruction to the compiler on how to treat the result.
Example: 1 - 2 (as 16 bit integers) will give 0xffff which is -1 for signed int, and 65535 for unsigned integer.
Therefore, if you want the signed difference between two unsigned integers, then
(int)(a - b);
I hope that helps.
Related
This question already has answers here:
c++ vector size. why -1 is greater than zero
(3 answers)
Closed 2 months ago.
I'm having trouble comparing size of a vector and simple constant -1
I believe both of these are logically the same:
(index >= (arr.size() - 1))
((index + 1) >= arr.size())
However, the first one returns 1 not 0.
What's the difference between the two comparisons?
#include <iostream>
#include <vector>
using namespace std;
int main() {
int index = -1;
vector<char> arr(6);
cout << (index >= (arr.size() - 1)) << endl;
cout << ((index + 1) >= arr.size()) << endl;
}
The arr.size method returns an unsigned integer type, so the type of the right-hand side of the comparison is unsigned. This results in the left side being converted to unsigned.
When the value on the left is -1, this gets converted to a very large unsigned number, resulting in the first comparison being true. In the second case, the value on the left is 0 so it doesn't change when being converted to an unsigned type and the comparison is false.
If you compile with -Wall -Wextra it will warn you about a signed / unsigned comparison.
size_t is an unsigned long long.
int is a signed type.
You are trying to compare an unsigned type with a signed one. The size of the vector will never have the value -1.
This question already has an answer here:
C++ size_t modulus operation with negative operand
(1 answer)
Closed 2 years ago.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
vector<int> v = {1, 2, 3, 4, 5, 6, 7};
int i = -4;
cout << i << endl;
cout << v.size() << endl;
cout << i % v.size() << endl;
cout << -4 % 7 << endl;
}
The above code prints:
-4
7
5
-4
Can someone please explain why i % v.size() prints 5 instead of -4? I'm guessing it has something to do with vector.size(), but unsure what the underlying reasoning is. Thanks in advance.
The operands of % undergo the usual arithmetic conversions to bring them to a common type, before the division is performed. If the operands were int and size_t, then the int is converted to size_t.
If size_t is 32-bit then -4 would become 4294967292 and then the result of the expression is 4294957292 % 7 which is actually 0.
If size_t is 64-bit then -4 would become 18,446,744,073,709,551,612 and the result of this % 7 is 5 which you saw.
So actually we can tell from this output that your system has 64-bit size_t.
In C++ the modulus operator is defined so that the following is true for all integers except for b == 0:
(a/b)*b + a%b == a
So it is forced to be consistent with the integer division, which from C++ 11 onwards truncates to zero even for negative numbers. Hence everything is well defined even for negative numbers.
However, in your case you have an signed / unsigned division (because .size() returns unsigned) and the usual signed/unsigned rules apply. This means that in this case all arguments are converted to unsigned before the operation is carried out (see also Ruslan's comment).
So -4 is converted to unsigned (and becomes a very large number) and then modulo is carried out.
You can also see this as 5 is not a correct answer for -4 modulo 7 with any definition of integer division (3 would be correct).
Arithmetic rules with C and C++ are not intuitive.
Because v.size return size_t.
cout << -4 % size_t(7) << endl; // 5
Take a look modulo-operator-with-negative-values
UPD: and signed-int-modulo-unsigned-int-produces-nonsense-results
This is due to the type of v.size(), which is an unsigned type. Due to integer promotion, this means that the result will also be treated as unsigned, despite i being a signed type.
I am assuming you are compiling on 64 bit. This means that in addition to promotion to unsigned, the result will also be of the 64 bit type unsigned long long. Step by step:
unsigned long long _i = (unsigned long long)-4; // 0xFFFFFFFFFFFFFFFC!
unsigned long long result = _i % (unsigned long long)7; // 5
Since presumably you want to preserve the signedness of i, in this case it is enough to cast v.size() to a signed type to prevent the promotion to unsigned:
i % (int)v.size() will give -4.
From cppreference on Usual arithmetic conversions and C++ standard
Otherwise (the signedness is different): If the unsigned type has conversion rank greater than or equal to the rank of the signed type, then the operand with the signed type is implicitly converted to the unsigned type.
-4 is signed and 7 is size_t which is an unsigned type, so -4 is converted to unsigned first and then modulus is carried out.
With that mind, if you break it down, you will immediately see what is happening:
size_t s = -4; // s = 18446744073709551612 on a 64 bit system
size_t m = 7;
std::cout << s % m << '\n'; //5
The results might be different for a 32-bit system.
cout << -4 % 7 << endl; still prints -4. Why? It's because the type of both -4 and 7 is int.
C++ standard ยง5.13.2.3 Type of an integer literal
The type of an integer-literal is the first type in the list in Table 8 corresponding to its optional integer-suffix in which its value can be represented. An integer-literal is a prvalue.
Table 8: Types of integer-literals without suffix:
int
long int
long long int
So, -4 and 7 both are int in this case and hence the result of modulo is -4.
This question already has answers here:
Comparison operation on unsigned and signed integers
(7 answers)
Closed 8 years ago.
this is my C code :
why is the output "False " ?????
why 4 > -1???
code :
#include <stdio.h>
int main() {
if (sizeof(int) > -1)
printf("True");
else
printf("False");
return 0;
}
Because sizeof(int) is unsigned. So -1 is converted to a large unsigned value.
Because sizeof yields a value of type size_t which is an unsigned type. In > expression usual arithmetic conversions will convert -1 to an unsigned type which is the type of the > result. The resulting value will be a huge positive value.
To get the expected behavior use:
(int) sizeof (int) > -1
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
int divided by unsigned int causing rollover
Hi I am doing the following:
struct coord{
int col;
};
int main(int argc, char* argv[]) {
coord c;
c.col = 0;
std::vector<coord> v;
for(int i = 0; i < 5; i++){
v.push_back(coord());
}
c.col += -13;
cout << " c.col is " << c.col << endl;
cout << " v size is " << v.size() << endl;
c.col /= v.size();
cout << c.col << endl;
}
and I get the following output:
c.col is -13
v size is 5
858993456
However, if I change the division line to c.col /= ((int)v.size()); I get the expected output:
c.col is -13
v size is 5
-2
Why is this?
This is a consequence of v.size() being unsigned.
See int divided by unsigned int causing rollover
The problem is that vector< ... >::size() returns size_t, which is a typedef for an unigned integer type. Obviously the problem arises when you divide a signed integer with an unsigned one.
std::vector::size returns a size_t which is an unsigned integer type, usually unsigned int. When you perform an arithmetic operation with an int and an unsigned int, the int operand is converted to unsigned int to perform the operation. In this case, -13 is converted to unsigned int, which is some number close to 4294967295 (FFFFFFFF in hexadecimal). And then that is divided by 5.
As stated, the reason is that a signed / unsigned division is performed by first converting the signed value to unsigned.
So, you need to prevent this by manually converting the unsigned value to a signed type.
There's a risk that v.size() could be too big for an int. But since the dividend does fit in an int, the result of the division is fairly boring when the divisor is bigger than that. So assuming 2's complement and no padding bits:
if (v.size() <= INT_MAX) {
c.col /= int(v.size());
} else if (c.col == INT_MIN && v.size() - 1 == INT_MAX) {
c.col = -1;
} else {
c.col = (-1 / 2);
}
In C++03, it's implementation-defined whether a negative value divided by a larger positive value is 0 or -1, hence the funny (-1 / 2). In C++11 you can just use 0.
To cover other representations than 2's complement you need to deal with the special cases differently.
This question already has answers here:
maximum value of int
(7 answers)
Closed 7 years ago.
Is there a C++ cross-platform library that provides me with a portable maximum integer number?
I want to declare:
const int MAX_NUM = /* call some library here */;
I use MSVC 2008 unmanaged.
In the C++ standard library header <limits>, you will find:
std::numeric_limits<int>::max()
Which will tell you the maximum value that can be stored in a variable of type int. numeric_limits is a class template, and you can pass it any of the numeric types to get the maximum value that they can hold.
The numeric_limits class template has a lot of other information about numeric types as well.
See limits.h (C) or climits (C++). In this case you would want the INT_MAX constant.
I know it's an old question but maybe someone can use this solution:
int size = 0; // Fill all bits with zero (0)
size = ~size; // Negate all bits, thus all bits are set to one (1)
So far we have -1 as result 'till size is a signed int.
size = (unsigned int)size >> 1; // Shift the bits of size one position to the right.
As Standard says, bits that are shifted in are 1 if variable is signed and negative and 0 if variable would be unsigned or signed and positive.
As size is signed and negativ we would shift in sign bit which is 1, which is not helping much, so we cast to unsigned int, forcing to shift in 0 instead, setting the sign bit to 0 while letting all other bits remain 1.
cout << size << endl; // Prints out size which is now set to maximum positive value.
We could also use a mask and xor but then we had to know the exact bitsize of the variable. With shifting in bits front, we don't have to know at any time how many bits the int has on machine or compiler nor need we include extra libraries.
I know the answer has been given but I just want to know from my old days, I used to do
int max = (unsigned int)-1
Will it give the same as
std::numeric_limits<int>::max()
?
On Hp UX with aCC compiler:
#include <iostream>
#include <limits>
using namespace std;
int main () {
if (sizeof(int)==sizeof(long)){
cout<<"sizeof int == sizeof long"<<endl;
} else {
cout<<"sizeof int != sizeof long"<<endl;
}
if (numeric_limits<int>::max()==numeric_limits<long>::max()){
cout<<"INT_MAX == lONG_MAX"<<endl;
} else {
cout<<"INT_MAX != LONG_MAX"<<endl;
}
cout << "Maximum value for int: " << numeric_limits<int>::max() << endl;
cout << "Maximum value for long: " << numeric_limits<long>::max() << endl;
return 0;
}
It prints:
sizeof int == sizeof long
INT_MAX != LONG_MAX
I checked both int and long types are 4bytes.
manpage limits(5) says that INT_MAX and LONG_MAX are both 2147483647
http://nixdoc.net/man-pages/HP-UX/man5/limits.5.html
So, conclusion std::numeric_limits< type >:: is not portable.