I'm facing a problem where signed integers should be converted to unsigneds, preserving their range and order.
Given the following definition:
#include <limits>
#define MIN(X) std::numeric_limits<X>::min();
#define MAX(X) std::numeric_limits<X>::max();
What is the fastest and correct way to map the signed range [MIN(T), MAX(T)] to the unsigned range [0, MAX(U)]?
where:
T is a signed integer type
U is an unsigned integer type
sizeof(T) == sizeof(U)
I tried various bit twiddling and numeric methods to come up with a solution, without success.
unsigned int signedToUnsigned(signed int s) {
unsigned int u = 1U + std::numeric_limits<int>::max();
u += s;
return u;
}
Live example here
This will add signed_max + 1
to signed int
to ensure [MIN(int), MAX(int)]
is mapped to [0, MAX(unsigned int)]
Why would this answer work and map correctly:
When you add a signed integral number to an unsigned, the signed number is promoted to unsigned type. From Section 4.7 [conv.integral]
If the destination type is unsigned, the resulting value is the least unsigned integer congruent to the source integer (modulo 2n where n is the number of bits used to represent the unsigned type). [ Note: In a two’s complement representation, this conversion is conceptual and there is no change in the bit pattern (if there is no truncation). —end note ]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With