Archived

This topic is now archived and is closed to further replies.

silvermace

signed or unsigned ???

Recommended Posts

The differences are max values and what they can store, basically. A signed number lets you store negative values - the sign representing positive or negative. Therefore, if you wanted the value '-30' you'd want a signed value. Unsigned values only allow positive values.

Signed numbers store their sign by using a bit of the variable to store positive or negative - if the bit is 1 then the value is negative, otherwise it's positive. This means that they will always have a smaller max value than their unsigned equivalent as they're not using the entire variable to store the value. For example, a signed 16-bit variable has the max value 2^15 but an unsigned variable has 2^16 (as it doesn't have to use a bit to say whether the number is negative).

EDIT: Just so it's clear - both can store the same range of values (for 16 bits = 65536), it's just the the maximum values are shifted. The signed number goes from –32768 to 32767 and the unsigned goes from 0 to 65536. Both ranges are the same, but the maximum value for the unsigned value is larger (65536 versus 32767). (This is the same for any data type, I just couldn't be bothered writing out the example for 32 bits ).

Use unsigned numbers where possible. They're quicker for the CPU to deal with and make more sense in some uses (for example, to store sizes and counts). The maximum value is higher too, which may be relevant in some cases. The only two times you'll want to use signed integers is when you expect a negative value and when you want to avoid converting between signed and unsigned values (which may require extending the result to a larger type, which will be slow).

[edited by - Alimonster on July 29, 2002 6:42:28 AM]

Share this post


Link to post
Share on other sites
Couple of things to add here:
Signed and unsigned variables are treated completely differently when bit-shifting right. Signed variables will sign-extend the high bit: it will pad the high bits with zeros if the original high bit was zero, and it will pad the high bits with ones if the original high bit was one. If your variable is unsigned, you''ll always get zeros padded when right-shifting.

Also, I''ve heard it said that if you switch a number from signed to unsigned to "gain one bit" in magnitude, you should seriously think about just bumping it up to the next largest storage type; it''s an indication that you''re close to overflowing and have under-estimated the size of that spot. Choosing unsigned often has unpleasant effects as far as conversion of pointers, etc., so unless it''s absolutely necessary (e.g. sign extension when shifting), you''re probably best of leaving everything its default, which is signed.

(BTW, this last paragraph of advice comes from Lakos''s "Large-Scale C++ Design"; I''m a little more than half-bought-into this argument, but not 100%, so take it with a grain of salt).

Share this post


Link to post
Share on other sites
quote:
Original post by Alimonster
Signed numbers store their sign by using a bit of the variable to store positive or negative - if the bit is 1 then the value is negative, otherwise it's positive.

Yep, it 'almost' work this way. Why I say almost? See here:

If you say 'that' is the sign bit, then:
32767 = 0111 1111 1111 1111
-32767 = 1111 1111 1111 1111
what about -32768?? It doesn't make sense to have -0 as -32768 if you says 'that' is the sign bit.
-------------------------------------------
It should be this way, eg. short /_int16 :
1: 0000 0000 0000 0001
...
32767: 0111 1111 1111 1111
-32768: 1000 0000 0000 0000
-32767: 1000 0000 0000 0001
...
-1: 1111 1111 1111 1111
--------------------------------------------
why not -1 = 1000 0000 0000 0001 ?
why not -0 = 1000 0000 0000 0000 (heheheh... )

Just search for 2's complement... then you should know.





[edited by - DerekSaw on July 29, 2002 9:26:15 PM]

[edited by - DerekSaw on July 29, 2002 9:27:16 PM]

Share this post


Link to post
Share on other sites
quote:

Use unsigned numbers where possible. They''re quicker for the CPU to deal with and make more sense in some uses (for example, to store sizes and counts).



There is no speed difference when it comes to signed versus unsigned integers. This is why I wish more people knew assembly language better.

The CPU doesn''t really make a distinction between signed and unsigned in the way that most programming languages do. When making comparisons, it''s just a matter of using different flags (those which assume the operands are signed vs. those which are for unsigned operands.) There are usually different shift right instructions (SHR for unsigned, SAR for signed) and MUL/DIV instructions (MUL, IMUL, DIV, IDIV.)

The same instructions are used for most operations, so it''s no big deal which you choose in terms of speed.


---
Bart

Share this post


Link to post
Share on other sites
LOL! Remind me never to make a definitive statement again. Anyway, I checked the "AMD Athlon x86 Code Optimization Guide" and this is its general recommendation for C-level optimisation:

Use unsigned types for:
* Division and remainders
* Loop counters
* Array indexing

Use signed types for:
* Integer-to-float conversion

(p19, chapter 3.)

Things it says (p18, chapter 3):
quote:
In many cases, the data stored in integer variables determines whether a signed or an unsigned integer type is appropriate. For example, to record the weight of a person in pounds, no negative numbers are required, so an unsigned type is
appropriate. However, recording temperatures in degrees Celsius may require both positive and negative numbers, so a signed type is needed.

Where there is a choice of using either a signed or an unsigned type, take into consideration that certain operations are faster with unsigned types while others are faster for signed types.

Integer-to-floating-point conversion using integers larger than 16 bits is faster with signed types


Not that it matters much, I guess. I tend to use unsigned ints for most loops, counts and sizes as they usually make more sense as non-negative.

I don''t see this is an especially religious issue (which is why I shouldn''t have made a definitive statement). Use whatever data type makes more sense in the situation (or take the other advice that it should always be signed).

Share this post


Link to post
Share on other sites
I agree that unsigned make more sense for array sizes \ loops, however I''ve had some difficult to find errors in my logic where I was attempting to access element -1 (Normally when looping through an array backwards and miscounting where to start \ stop). In this case it took me a while to locate the code as it ''looked'' correct. The reason here is that the unsigned int was underflowing(term?) after it hit zero and an array element of size::unsigned int didn''t exist

Sometimes using signed anyway is better for debugging. That said, I don''t follow my own advice and use unsigned anyway

Chris Brodie
http:\\fourth.flipcode.com

Share this post


Link to post
Share on other sites