Why am I getting errors when using unsigned integers in an expression with C ++?
Considering the following piece of code (pseudo C ++):
float x=100, a=0.1;
unsigned int height = 63, width = 63;
unsigned int hw=31;
for (int row=0; row < height; ++row)
{
for (int col=0; col < width; ++col)
{
float foo = x + col - hw + a * (col - hw);
cout << foo << " ";
}
cout << endl;
}
The foo values ββare screwed in half the array, where (col-hw) is negative. I realized that col is int and in the first place, that this part of the expression is converted to int and becomes negative. Unfortunately this does not appear to be happening, I am getting a signed value overflow and I have no idea why.
How can I solve this problem? Use broadcasts for all or part of an expression? What type of butts (C-style or static_cast <...>)? Is there an overhead of using casts (I need this to work fast!)?
EDIT: I changed all my unsigned ints to regular ones, but I'm still wondering why I got this overflow in this situation.
a source to share
Unsigned integers implement unsigned arithmetic. Unsigned arithmetic is modular arithmetic. All values ββare adjusted modulo 2 ^ N, where N is the number of bits in the representation of unsigned values.
In simple words, unsigned arithmetic always produces non-negative values. Whenever an expression must result in a negative value, the value actually wraps around 2 ^ N and becomes positive.
When you mix signed and unsigned integer in the [sub] expression, the assigned arithmetic "wins"; calculations are performed on an unsigned domain. For example, when you execute col - hw
, it is interpreted as (unsigned) col - hw
. This means that for col == 0
and hs == 31
you will not get -31
as a result. Instead, you get UINT_MAX - 31 + 1
, which is usually a huge positive value.
Having said that, I should point out that it is always useful in my opinion to use unsigned types to represent inherent non-negative values. In fact, in practice, most (or at least half) of the integer variables in a C / C ++ program must be of unsigned types. Your attempt to use unsigned types in your example is well founded (if you understand the intent correctly). Moreover, I would use unsigned
for col
androw
... However, you must keep in mind how unsigned arithmetic works (as described above) and write your expressions accordingly. In most cases, the expression can be rewritten so that it does not cross the boundaries of the unsigned range, that is, in most cases there is no need to explicitly cast anything to a signed type. Otherwise, if you need to work with negative values, in the end, the correct signed type approach should solve the problem.
a source to share
How to make height
, width
and hw
signed ints? What are you really typing by making them unsigned? Mixing signed and unsigned integers always causes problems. At first glance, at least it looks like you're not getting anything using unsigned values ββhere. This way you can also make them signed and save yourself the trouble.
a source to share
If you want this to be fast, you must statically_map all unsigned values ββbefore starting the loop and use their int versions, not unsigned int versions. You can still require unsigned inputs and then just drop them in your algorithm path to keep the required domain for your function.
a source to share