1

I have a double in the range (0,1) which I want to scale to the full range of a 32-bit unsigned int (0,0xFFFFFFFF).

How can I do this in C++? I am not concerned about the edge cases, so long as there isn't any nasty overflows where the result wraps around.

Thanks

Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
user593062
  • 1,593
  • 4
  • 15
  • 24

2 Answers2

2

Solution with C++11's lround:

uint32_t convert_to(double v) {
  return std::lround(v * std::numeric_limits<uint32_t>::max());
}

double convert_from(uint32_t v) {
  return static_cast<double>(v) / std::numeric_limits<uint32_t>::max();
}

Without lround (round() for float in C++):

uint32_t convert_to(double v) {
  return std::floor(v * std::numeric_limits<uint32_t>::max() + 0.5);
}
Community
  • 1
  • 1
R1tschY
  • 3,032
  • 1
  • 24
  • 30
  • `double test = 0.82004366063971901; unsigned __int32 result = std::lround(test * std::numeric_limits::max());` result is zero. ?? – user593062 Sep 12 '14 at 01:22
  • @user593062: I don't see any problem: http://coliru.stacked-crooked.com/a/fc3a94aff87e477a – R1tschY Sep 12 '14 at 08:12
1

Well, you can simply do this

unsigned int result = (unsigned int)std::floor( 
    std::numeric_limits<unsigned int>::max() * yourDoubleInRange01 );
grzkv
  • 2,599
  • 3
  • 26
  • 37
  • An overflow will happen if `yourDoubleInRange01` is bigger than `0.5`. Use a 32-bit unsigned int (`uint32_t`) for `result` and the conversion. – R1tschY Sep 11 '14 at 16:04
  • To round the result, .5 could be added to the product, unsigned int result = (unsigned int)std::floor(.5 + (std::numeric_limits::max() * yourDoubleInRange01) ); – rcgldr Sep 11 '14 at 17:58