'Narrowing conversion on a (int64_t * static_cast<float>(double))

I'm fixing some lint errors in a codebase I am working with, and I see the following line

// note offset is int64_t, scale is int64_t, x is double
int64_t y = offset + lrintf(scale * static_cast<float>(x))

the linter complains and says narrowing conversion from 'int64_t' (aka 'long') to 'float'.

It seems the scale * static_cast<float>(x) is what's causing issues, and I'm wondering what is the best way to handle this error? should I cast scale to a double, and then call lrintd instead? Or is there a better approach for this case?



Solution 1:[1]

You're right. The static_cast discards some bits from the mantissa and exponent. This also limits the number of bits in the mantissa of float(scale).

Note that a typical IEEE754 double also has insufficient bits in the mantissa to fully express every int64_t value. That's logical: both are 8 byte types. But float is only 4 bytes in IEEE754.

Solution 2:[2]

Seems more logical to use

int64_t y = offset + llrint(scale * x);

scale * x will be double and should be rounded to long long (AKA int64_t).

Note anyway that this might modify the program behavior in some cases (truncating the double to float or not could result in different y).

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 MSalters
Solution 2 Yves Daoust