因为从 [0.0f .. 1.0f] 到 [0 .. UInt32.MaxValue] 的乘法本身可以是近似的,所以最明显具有您想要的属性的操作顺序是乘法,然后是钳位,然后是舍入。
要钳制到的最大值是 2 32正下方的浮点数,即4294967040.0f
. 虽然这个数字比 UInt32.MaxValue 低几个单位,但允许任何更大的值都意味着转换为UInt32
.
下面的任何一行都应该工作:
y = (uint)round(min(max(x * 4294967040.0F, 0.0F), 4294967040.0F))
在第一个版本中,您可以选择乘以UInt32.MaxValue
。选择是在总体上获得稍微大一点的结果(因此将接近 1.0f 但低于它的更多值四舍五入到 4294967040),或者只将 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)
这个计算被认为是一个函数 from x
toy
正在增加(包括大约 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 = ...
}