0

I have to implement two functions that convert signed to unsigned and vice versa. I am using c++11 and Linux.

The system is two's complement and can take char, int, long etc.. The interface must be as stated and I have tried to implement something. Are there better ways to do this? Are these correct? How can I change the implementation based on the number of bits? I need some advice.

uint32_t signedToUnsigned(int32_t x, uint8_t bits)
{
    return ( x > 0 ? x:-x);
}

int32_t unsignedToSigned(uint32_t x, uint8_t bits)
{
    if(x <= INT_MAX )
        return static_cast<int>(x);

    if(x >= INT_MIN)
        return static_cast<int>(x - INT_MIN)+ INT_MIN;
    else
    {
        printf("ERROR");
        return x;
    }
}

EDIT:

I need to specifiy the bits as this will be used with HW. So, I may need to limit the value in the return type to 18bits or 4 etc...

jww
  • 97,681
  • 90
  • 411
  • 885
user1876942
  • 1,411
  • 2
  • 20
  • 32
  • 1
    what's the use of second argument bits here? – Dr. Debasish Jana Sep 25 '14 at 10:45
  • Your `unsignedToSigned()` function is broken. Think it through for a case where `x` is larger than `INT_MAX` or smaller than `INT_MIN`, and you will see what I mean. If your argument is `int32_t` (fixed 32 bits), that pretty much *decides* how many bits there are, doesn't it? All in all, hard to tell what your question is, really... – DevSolar Sep 25 '14 at 10:46
  • Maybe nothing, I was wondering if I need to change the code based on the type used, like int or char etc.. – user1876942 Sep 25 '14 at 10:47
  • @user1876942: I am not sure what these functions should be used for *at all*, since two's complement already *has* rather nice handling of unsigned-signed-unsigned casting already... – DevSolar Sep 25 '14 at 10:48
  • @user1876942 This condition if(x >= INT_MIN) is always equal to true because UINT_MIN is equal to 0 and in any case is greater than INT_MIN. So the next else statement has no sense.:) – Vlad from Moscow Sep 25 '14 at 10:48
  • @DevSolar, can you give an example? – user1876942 Sep 25 '14 at 10:50
  • 2
    "Are these correct?" Yes, for certain special values of "correct". You need to **define** what the conversion should do in case of target type being unable to represent the value, then check your implementation against your definition. – n. m. could be an AI Sep 25 '14 at 10:51
  • 1
    @@user1876942 How are you going to convert an unsigned value to signed value if the unsigned value is greater than INT_MAX? – Vlad from Moscow Sep 25 '14 at 10:53
  • 3
    @user1876942: Not really, because I cannot figure out what your `unsignedToSigned()` function is *supposed* to do. (What it *does* do makes no sense at all.) So: What's wrong with simply `static_cast()` that `unsignedToSigned()` should be fixing? – DevSolar Sep 25 '14 at 10:57
  • @DevSolar, Will that always work? For some reason I thought not. I will need to check if that is OK. Simpler anyhow. Thanks. – user1876942 Sep 25 '14 at 11:07
  • 2
    @user1876942: I don't know if it will "work" *because you are not clear about what your requirements are and your current implementation is bugged.* – DevSolar Sep 26 '14 at 07:57
  • 1
    @user1876942 Your edit does not clarify your expectations. If you are converting a negative number to unsigned you want its absolute value? If you are converting a unsigned number greater than the max signed number, you want what? If returning too few bits to represent the number do you just want to preserve the least-significant-bits as your return value? If returning too few bits to represent a signed number do you want to preserve the sign in the bits returned as well? Please add these expectations to your question. – Jonathan Mee Sep 26 '14 at 11:46

2 Answers2

1

Instead of having dependency of no of bits have overloaded functions as:

uint32_t signedToUnsigned(int32_t x);
uint64_t signedToUnsigned(int64_t x);
uint16_t signedToUnsigned(int16_t x);

and so on. However, simple static_cast should do, please read: How does one safely static_cast between unsigned int and int?

Community
  • 1
  • 1
Dr. Debasish Jana
  • 6,980
  • 4
  • 30
  • 69
  • I will check out that static_cast. What about going the other way, signedToUnsigned? – user1876942 Sep 25 '14 at 11:12
  • similarly you can go for signedToUnsigned – Dr. Debasish Jana Sep 25 '14 at 11:15
  • @user1876942: Your `signedToUnsigned()` is implemented as [`std::abs()`](http://en.cppreference.com/w/cpp/numeric/math/abs) (for "absolute value") in the standard library (). – DevSolar Sep 25 '14 at 11:16
  • Std::abs does not support 16bit. Therefore -32768 gives 32768 but in 16bit it should be 32767. – user1876942 Sep 25 '14 at 11:54
  • 1
    @user1876942 I suspect that you are using the C abs function included in `cmath`. At the top of your file you should `#include ` which will give you the templatized C++ version of `std::abs` and return `32767`. – Jonathan Mee Sep 25 '14 at 15:04
  • @Jonathan,do you know if there is a way to specifiy the number of bits to limit the operation to? So, 4bit, 12, or 18 etc.. As I will use it with HW registers. – user1876942 Sep 25 '14 at 17:24
  • 1
    @user1876942 It sounds like what you really want is (`std::bitset`)[http://www.cplusplus.com/reference/bitset/bitset/]. You can see the operators here: http://www.cplusplus.com/reference/bitset/bitset/operators/. It sounds like you wanna play special attention to `operator~`. – Jonathan Mee Sep 25 '14 at 17:55
  • @user1876942 I'd also recommend that you take the time to go through and accept answers on your questions. A lot of people are putting in time helping you. The least you can do is also contribute by accepting answers. – Jonathan Mee Sep 25 '14 at 17:56
1

If you want a number to survive a round trip your functions are not good.

For example: std::cout << unsignedToSigned( signedToUnsigned( -13, 0 ), 0 ); // prints 13 NOT -13

static_cast will survive the round trip: std::cout << static_cast< int32_t >( static_cast< uint32_t >( -13 ) ); // prints -13

So I think static_cast is what you want unless you can update the question with a clearer specification.

Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288