当一个值可能太大而无法完全适合另一个类型时,比较一个32位浮点数和一个32位整数而不转换为double [英] Compare a 32 bit float and a 32 bit integer without casting to double, when either value could be too large to fit the other type exactly
问题描述
我有一个32位浮点f
数字(已知为正数),我需要将其转换为32位无符号整数.它的大小可能太大而无法容纳.此外,存在下游计算需要一定的余量.我可以将最大可接受值m
计算为32位整数.如果在数学上f <= m
,如何在受限的32位计算机(ARM M4F)上的C ++ 11中有效确定.请注意,两个值的类型不匹配.以下三种方法各有其问题:
I have a 32 bit floating point f
number (known to be positive) that I need to convert to 32 bit unsigned integer. It's magnitude might be too large to fit. Furthermore, there is downstream computation that requires some headroom. I can compute the maximum acceptable value m
as a 32 bit integer. How do I efficiently determine in C++11 on a constrained 32 bit machine (ARM M4F) if f <= m
mathematically. Note that the types of the two values don't match. The following three approaches each have their issues:
-
static_cast<uint32_t>(f) <= m
:如果f
不适合32位整数,我认为这会触发未定义的行为 -
f <= static_cast<float>(m)
:如果m
太大而无法精确转换,则转换后的值可能大于m
,这样在某些边缘情况下后续的比较将产生错误的结果 -
static_cast<double>(f) <= static_cast<double>(m)
:在数学上是正确的,但是需要强制转换为double并使用double,出于效率原因,我希望避免这种情况
static_cast<uint32_t>(f) <= m
: I think this triggers undefined behaviour iff
doesn't fit the 32 bit integerf <= static_cast<float>(m)
: ifm
is too large to be converted exactly, the converted value could be larger thanm
such that the subsequent comparison will produce the wrong result in certain edge casesstatic_cast<double>(f) <= static_cast<double>(m)
: is mathematically correct, but requires casting to, and working with double, which I'd like to avoid for efficiency reasons
肯定有一种方法可以直接将整数转换为具有指定舍入方向的浮点数,即保证结果的大小不超过输入值.我更喜欢C ++ 11标准解决方案,但在最坏的情况下,平台内在函数也可能合格.
Surely there must be a way to convert an integer to a float directly with specified rounding direction, i.e. guaranteeing the result not to exceed the input in magnitude. I'd prefer a C++11 standard solution, but in the worst case platform intrinsics could qualify as well.
推荐答案
我认为您最好的选择是针对特定平台. 2³²可以精确地表示为浮点数.检查f
是否太大而根本无法容纳,然后转换为unsigned并对照m
进行检查.
I think your best bet is to be a bit platform specific. 2³² can be represented precisely in floating point. Check if f
is too large to fit at all, and then convert to unsigned and check against m
.
const float unsigned_limit = 4294967296.0f;
bool ok = false;
if (f < unsigned_limit)
{
const auto uf = static_cast<unsigned int>(f);
if (uf <= m)
{
ok = true;
}
}
不喜欢双重比较,但是很明显.
Not fond of the double comparison, but it's clear.
如果f
通常显着小于m
(或者通常显着大于),则可以针对float(m)*0.99f
(分别为float(m)*1.01f
)进行测试,然后在异常情况下进行精确比较.只有在性能分析表明性能提升值得额外的复杂性时,这才值得做.
If f
is usually significantly less than m
(or usually significantly greater), one can test against float(m)*0.99f
(respectively float(m)*1.01f
), and then do the exact comparison in the unusual case. That is probably only worth doing if profiling shows that the performance gain is worth the extra complexity.
这篇关于当一个值可能太大而无法完全适合另一个类型时,比较一个32位浮点数和一个32位整数而不转换为double的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!