Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert uint32_t to double between 0 and 1 [closed]

Tags:

c++

I have a shamefully naive question: What is the best way to convert a uint32_t to a double between 0 and 1?

My naive way is

double myconvert(uint32_t a)
{
    double n = static_cast<double>(std::numeric_limits<uint32_t>::max() - std::numeric_limits<uint32_t>::min());
    return static_cast<double>(a) / n;
}

But I was wondering if there is a better way?

like image 491
Tom de Geus Avatar asked Apr 20 '21 14:04

Tom de Geus


Video Answer


3 Answers

std::numeric_limits<uint32_t>::min() is 0. Although removing the subtraction doesn't improve the generated assembly since it is known at compile time, it can simplify the function.

Another potential improvement is to calculate the complement of the divisor and use multiplication. You might think that optimiser would do that conversion automatically, but that's often not possible with floating point due to strict rules of IEEE-754.

Example:

return a * (1.0 / std::numeric_limits<uint32_t>::max());

Note that in the division used to calculate the complement, both operands are known at compile time, so the division is pre-calculated.

As you can see here, GCC does not do the optimisation automatically. It does if you use -ffast-math at the cost of IEEE-754 conformance

I checked Agner Fog's instruction tables and randomly chose Zen3 architecture, and double division has about 3 times greater latency than multiplication.

like image 100
eerorika Avatar answered Oct 17 '22 09:10

eerorika


It is safe to assume that std::numeric_limits<uint32_t>::min() will be zero (what unsigned integer is less than this?), so you can simplify your formula considerably:

double myconvert(uint32_t a)
{
    return static_cast<double>(a) / std::numeric_limits<uint32_t>::max();
}
like image 26
Adrian Mole Avatar answered Oct 17 '22 07:10

Adrian Mole


1.0 * a / std::numeric_limits<uint32_t>::max()

is one way.

like image 32
Bathsheba Avatar answered Oct 17 '22 09:10

Bathsheba