转换上浮到UInt32的 - 这表达更精确 [英] Converting float to UInt32 - which expression is more precise

查看:353
本文介绍了转换上浮到UInt32的 - 这表达更精确的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我公司拥有一批浮法X 这应该是上述< 0,1>范围内,但经过几个数值运算 - 结果可能会稍微外℃下, 1>。

I have a number float x which should be in <0,1> range but it undergo several numerical operations - the result may be slightly outside <0,1>.

我需要使用 UINT是> UInt32的。当然,我需要用镊子 X 在< 0,1>的范围和规模。

I need to convert this result to uint y using entire range of UInt32. Of course, I need to clamp x in the <0,1> range and scale it.

不过,哪些操作的顺序是更好的?

But which order of operations is better?

y = (uint)round(min(max(x, 0.0F), 1.0F) * UInt32.MaxValue)

y = (uint)round(min(max(x * UInt32.MaxValue, 0.0F), UInt32.MaxValue)

在换句话说,最好是先规模,再用镊子或钳,然后扩展?我不是在IEEE浮点表示很深刻,但我相信有在上述表达式的计算的顺序的差异。

In another words, it is better to scale first, then clamp OR clamp and then scale? I am not very profound in the IEEE floating point representation, but I believe there is a difference in the order of computation of the above expressions.

推荐答案

由于乘法从[0.0 .. 1.0F得到]到[0 .. UInt32.MaxValue]本身可以是近似,大多数显然有你想要的属性操作的顺序是乘法,然后夹紧,然后轮

Because the multiplication to get from [0.0f .. 1.0f] to [0 .. UInt32.MaxValue] can itself be approximative, the order of operations that most obviously has the property you desire is multiply, then clamp, then round.

夹到的最大值是浮动下方2 32 ,即 4294967040.0f 。虽然这个数字是几台下面UInt32.MaxValue,允许任何值越大就意味着溢出转换为 UInt32的

The maximum value to clamp to is the float immediately below 232, that is, 4294967040.0f. Although this number is several units below UInt32.MaxValue, allowing any larger value would mean overflowing the conversion to UInt32.

无论下面的行应该工作:

Either of the lines below should work:

y = (uint)round(min(max(x * 4294967040.0F, 0.0F), 4294967040.0F))

在这第一个版本,你必须通过<$乘以选项C $ C> UInt32.MaxValue 来代替。这个选择是非常有稍大结果总体(因而四舍五入到4294967040这已接近1.0F,但它下面几个值),或者只发送给4294967040值1.0F及以上的。

In this first version, you have the option to multiply by UInt32.MaxValue instead. The choice is between having very slightly larger results overall (and thus rounding to 4294967040 a few more values that were close to 1.0f but below it), or only sending to 4294967040 the values 1.0f and above.

您还可以钳[0.0 .. 1.0F] 如果您不要得大一些之后乘以 ,所以,没有使超过可转换的最大的浮法值越大的风险:

You can also clamp to [0.0f .. 1.0f] if you do not multiply by too large a number afterwards, so that there is no risk of making the value larger than the largest float that can be converted:

y = (uint)round(min(max(x, 0.0F), 1.0F) * 4294967040.0F)






建议下面您的评论,有关各具特色的上升到 UInt32.MaxValue 转换:

if (x <= 0.0f) y = 0
else if (x < 0.5f) y = (uint) round (x * 4294967296.0F)
else if (x >= 1.0f) y = UInt32.MaxValue
else y = UInt32.MaxValue - (uint) round ((1.0f - x) * 4294967296.0F)

该计算从 X视为一个函数到正在增加(包括周围0.5F),并将其上升到 UInt32.MaxValue 。你可以根据你的想法将是值的最可能的分布重新排列测试。特别是,假设几个值实际上是低于0.0或高于1.0F,你可以比较0.5F第一,然后只比较绑定是相关的:

This computation considered as a function from x to y is increasing (including around 0.5f) and it goes up to UInt32.MaxValue. You can re-order the tests according to what you think will be the most likely distribution of values. In particular, assuming that few values are actually below 0.0f or above 1.0f, you can compare to 0.5f first, and then only compare to the bound that is relevant:

if (x < 0.5f)
{
  if (x <= 0.0f) y = ...
  else y = ...
}
else
{
  if (x >= 1.0f) y = ...
  else y = ...
}

这篇关于转换上浮到UInt32的 - 这表达更精确的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆