因为从 [0.0f .. 1.0f] 到 [0 .. UInt32.MaxValue] 的乘法本身可以是近似的,所以最明显具有您想要的属性的操作顺序是乘法,然后钳位,然后舍入。
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
.
以下任一行都应该有效:
y = (uint)round(min(max(x * 4294967040.0F, 0.0F), 4294967040.0F))
在第一个版本中,您可以选择乘以UInt32.MaxValue
反而。选择是总体结果稍大一些(因此舍入到 4294967040 一些接近 1.0f 但低于它的值),或者仅将 1.0f 及以上的值发送到 4294967040。
您还可以钳位到 [0.0f .. 1.0f]如果你之后没有乘以太大的数字,这样就不会有使值大于可转换的最大浮点数的风险:
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
to y
正在增加(包括 0.5f 左右)并且上升到UInt32.MaxValue
。您可以根据您认为最可能的值分布对测试重新排序。特别是,假设实际上很少有值低于 0.0f 或高于 1.0f,您可以首先与 0.5f 进行比较,然后仅与相关的界限进行比较:
if (x < 0.5f)
{
if (x <= 0.0f) y = ...
else y = ...
}
else
{
if (x >= 1.0f) y = ...
else y = ...
}