Конвертировать двойные, чтобы плавать без бесконечности - PullRequest
28 голосов
/ 10 июля 2011

Я конвертирую double в float, используя старые float myFloat = (float)myDouble.

Однако иногда это приводит к «Бесконечности», что не годится для дальнейшей обработки, которую я делаю. Я в порядке с потерей, если он указывает в общем направлении как исходное число (относительное число «сила» на всех числах, которые я конвертирую, должно быть сохранено).

Как я могу преобразовать число с плавающей запятой в удвоение и избежать бесконечности?

Фон:
Я читаю поток данных из wav / mic, преобразовываю его в float, преобразовываю в double, запускаю с помощью вычисления FFT (для этого требуется double), и теперь я хочу вернуть его к float (хранение данных в 32-битном контейнере изображений).

Ответы [ 4 ]

33 голосов
/ 10 июля 2011

Итак, если значение больше float.MaxValue, вы рады, что оно просто равно float.MaxValue? Это эффективно «обрезает» значения. Если все в порядке, это достаточно просто:

float result = (float) input;
if (float.IsPositiveInfinity(result))
{
    result = float.MaxValue;
} else if (float.IsNegativeInfinity(result))
{
    result = float.MinValue;
}
15 голосов
/ 02 декабря 2013

Вы можете использовать метод .NET Convert.ToSingle().Например:

float newValue = Convert.ToSingle(value);

Согласно документации MSDN :

Преобразует указанное значение в число с плавающей запятой одинарной точности.

Обновление: При дальнейшем рассмотрении Convert.ToSingle(Double.MaxValue) приводит к бесконечности, поэтому вам все равно придется проверять бесконечность, как было сделано в ответе Джона Скита.

1 голос
/ 31 мая 2012

Если результат вычисления превышает диапазон того типа, в котором вы его храните, необходимо выполнить одно из трех действий:

  1. Брось исключение
  2. Возвращает значение «часовой», которое указывает, что возникла проблема, и которое будет предпочтительно распознаваться как фактически лишающее законной силы любые вычисления, где оно появляется
  3. Привязать результат к какому-либо определенному значению (к которому он будет привязан, даже если он не превышает диапазон вашего числового типа). Например, можно иметь датчик в сборе с двумя усредненными по времени входами X и Y, чье «значение» равно (X * X) / (Y * Y) - (Y * Y) / (X * X). Если входы шумят, низкое значение на одном входе может быть прочитано как исключительно низкое значение. Если измерение будет использоваться для управления контуром обратной связи, и если «фактическое» значение не будет превышать +/- 1000000.0, может быть лучше привязать значение к этому диапазону, чем позволить контрольному циклу видеть полностью вычисленные значения чтение (X или Y - наименьшее возможное ненулевое значение).

Есть много приложений, где третий подход был бы правильным. Однако в таких ситуациях, если имеет смысл привязать показание к значению в миллион, тогда не должно иметь значения, приведет ли вычисление к значению 1,000,001 или 1E + 39 (с плавающей запятой + INF). В любом случае нужно привязать к миллиону.

0 голосов
/ 13 марта 2017

Используйте эту функцию

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);
    }
...