比较一个 32 位浮点数和一个 32 位整数而不转换为双精度值,当任一值可能太大而无法完全适合另一种类型时
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。请注意,这两个值的类型不匹配。以下三种方法各有其问题:
static_cast<uint32_t>(f) <= m
:如果 f
不适合 32 位整数 ,我认为这会触发未定义的行为
f <= static_cast<float>(m)
:如果m
太大而无法准确转换,转换后的值可能会大于m
,这样后续比较会在某条边上产生错误的结果案例
static_cast<double>(f) <= static_cast<double>(m)
:在数学上是正确的,但需要转换为 double 并使用它,出于效率原因我想避免这种情况
肯定有办法把整数直接转为浮点数,指定舍入方向,即保证结果不超过输入的量级。我更喜欢 C++11 标准解决方案,但在最坏的情况下,平台内在函数也有资格。
我认为您最好的选择是针对特定平台。 2³² 可以用浮点数精确表示。检查 f
是否太大而根本无法容纳,然后转换为无符号并检查 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;
}
}
不喜欢双重比较,但是很清楚。
如果 f
通常明显小于 m
(或通常明显大于),可以针对 float(m)*0.99f
(分别为 float(m)*1.01f
)进行测试,然后执行异常情况下的精确比较。这可能只有在分析表明性能提升值得额外的复杂性时才值得这样做。
我有一个 32 位浮点数 f
(已知为正数),我需要将其转换为 32 位无符号整数。它的大小可能太大而不适合。此外,下游计算需要一些净空。我可以将最大可接受值 m
计算为 32 位整数。如果数学上 f <= m
,我如何在受约束的 32 位机器 (ARM M4F) 上有效地确定 C++11。请注意,这两个值的类型不匹配。以下三种方法各有其问题:
static_cast<uint32_t>(f) <= m
:如果f
不适合 32 位整数 ,我认为这会触发未定义的行为
f <= static_cast<float>(m)
:如果m
太大而无法准确转换,转换后的值可能会大于m
,这样后续比较会在某条边上产生错误的结果案例static_cast<double>(f) <= static_cast<double>(m)
:在数学上是正确的,但需要转换为 double 并使用它,出于效率原因我想避免这种情况
肯定有办法把整数直接转为浮点数,指定舍入方向,即保证结果不超过输入的量级。我更喜欢 C++11 标准解决方案,但在最坏的情况下,平台内在函数也有资格。
我认为您最好的选择是针对特定平台。 2³² 可以用浮点数精确表示。检查 f
是否太大而根本无法容纳,然后转换为无符号并检查 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;
}
}
不喜欢双重比较,但是很清楚。
如果 f
通常明显小于 m
(或通常明显大于),可以针对 float(m)*0.99f
(分别为 float(m)*1.01f
)进行测试,然后执行异常情况下的精确比较。这可能只有在分析表明性能提升值得额外的复杂性时才值得这样做。