[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)
x
からまでの関数と見なされるこの計算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 = ...
}