web-dev-qa-db-ja.com

Infinityなしでdoubleをfloatに変換します

古いfloat myFloat = (float)myDoubleを使用してdoubleをfloatに変換しています。

ただし、これにより「Infinity」が発生する場合があり、これは今後の処理には適していません。元の数値として一般的な方向を指している限り、損失は問題ありません(変換するすべての数値の相対的な数値「強度」を維持する必要があります)。

Floatをdoubleに変換してInfinityを回避するにはどうすればよいですか?

バックグラウンド:
wav/micからバイトストリームを読み取り、floatに変換し、doubleに変換し、FFT計算を実行しています(これにはdouble)、そして今私はそれをfloatに戻したい(32ビット画像コンテナにデータを保存する)。

28
Tedd Hansen

値がfloat.MaxValueより大きい場合、それがfloat.MaxValueになっていることに満足していますか?これにより、値が効果的に「クリップ」されます。それが大丈夫なら、それはかなり簡単です:

float result = (float) input;
if (float.IsPositiveInfinity(result))
{
    result = float.MaxValue;
} else if (float.IsNegativeInfinity(result))
{
    result = float.MinValue;
}
34
Jon Skeet

.NETメソッドConvert.ToSingle()を使用できます。例えば:

_float newValue = Convert.ToSingle(value);
_

MSDNドキュメント によると:

指定された値を単精度浮動小数点数に変換します。

更新:さらにレビューすると、Convert.ToSingle(Double.MaxValue)はInfinityになるため、Jon Skeetの答えで行われたように、無限をチェックする必要があります。

15
BryanJ

計算の計算結果が保存している型の範囲を超える場合、次の3つのいずれかを実行する必要があります。

  1. 例外を投げる
  2. 問題があったことを示す「センチネル」値を返す
  3. 結果を特定の値にペグします(数値タイプの範囲を超えていない場合でも、ペグされます)。たとえば、2つの時間平均入力XおよびYを備えたセンサーアセンブリがあり、その「値」は(X * X)/(Y * Y)-(Y * Y)/(X * X)です。入力にノイズが多い場合、1つの入力の低い値が非常に低い値として読み取られることがあります。フィードバックループの制御に測定値が使用され、「実際の」値が+/- 1000000.0を超えない場合、制御ループに計算された完全にワイルドな表示よりも、その範囲に値をペグする方がよい場合があります読み取り値(XまたはYは、ゼロ以外の最小値です)。

3番目のアプローチが適切なアプリケーションが多数あります。ただし、このような状況では、読み取り値を100万の値に固定することが理にかなっている場合、計算結果が1,000,001または1E + 39(浮動小数点+ INF)の値になるかどうかは問題ではありません。いずれの場合も、100万に固定する必要があります。

1
supercat

この機能を使用

public static float DoubleToFloat(double dValue)
    {
        if (float.IsPositiveInfinity(Convert.ToSingle(dValue)))
        {
            return float.MaxValue;
        }
        if (float.IsNegativeInfinity(Convert.ToSingle(dValue)))
        {
            return float.MinValue;
        }
        return Convert.ToSingle(dValue);
    }