tags:

views:

213

answers:

2

In C I need to scale a uint8_t from 0 - 255 to 0 - 31

What is the best way to do this evenly?

+12  A: 

If you're trying to scale from 8 bits to 5 bits, you can do a 3 bit shift;

uint8_t scaled = (uint8_t)(original >> 3);

This drops the lower 3 bits.

Daniel LeCheminant
I think the rounded value will fail if you have an original which is above (255 - 15).
Laserallan
@Laserallan: Lol, I noticed that too! (I must have been editing while you made the comment)
Daniel LeCheminant
Don't round. Your first answer is the right one I think. It evenly distributes the results.
Jason S
yeah i think the cast isn't necassary: promotion takes care of converting it to int automagically ("usual arithmetical conversions"). so you have now (int)(uint16_t)original + 4 effectively. without the cast, you have ((int)original + 4) . u get overflow if you do something like original += 4.
Johannes Schaub - litb
if your int is 32 bits, anyway :) if you got a 16bit int, then both will be converted to (unsigned int) with your explicit cast to uint16_t first :). but both will be int without an explicit cast because int at least has 16bits. anyway, i won't appear as a nitpicker so i +1 you as it is :)
Johannes Schaub - litb
Mathematically, shifting 3 bits is the same as a floor(N/8). In this case, it can be thought of as putting 256 values from an 8-bit integer into 32 groups, where each value in a group is numbered 0-7. The lowest 3 bits then don't matter as they only identify a value within a group.
Will Bickford
@Jason: I agree that the rounding is both unnecessary and is in fact wrong (255 for example would become 0!)
Daniel LeCheminant
+1  A: 

You can use some simple multiplication and division:

uint8_t scaled = (uint8_t)(((uint32_t)original * 32U) / 256U);
sixlettervariables
I'm not sure, but may want to cast original to something larger to avoid truncation due to overflow with that * 32.
Evan Teran
Touche salesman.
sixlettervariables
FYI, This answer is the same as scaled = (original << 5) >> 8, which is the same as scale = original >> 3, which is the same as the accepted answer.
SoapBox
Agreed. Left for readability nuts.
sixlettervariables