Преобразование двойного плавания без бесконечности
Я конвертирую double в float, используя старые float myFloat = (float)myDouble
.
Однако это иногда приводит к "бесконечности", что плохо для дальнейшей обработки, которую я делаю. Я в порядке с потерей, пока он указывает на общее направление, поскольку исходное число (относительное число "сила" для всех чисел, которые я конвертирую, должно поддерживаться).
Как преобразовать float в double и избежать бесконечности?
Справочная информация:
Я читаю байтовый поток из wav/mic, преобразовывая его в float
, преобразовывая его в double
, запуская его с помощью вычисления FFT (это то, что требует double
), и теперь я хочу, чтобы он вернулся к float
(сохранение данных в 32-битном контейнере изображений).
Ответы
Ответ 1
Итак, если значение больше, чем float.MaxValue
, вы довольны тем, что это просто float.MaxValue
? Это эффективно "закрепит" значения. Если это хорошо, это достаточно просто:
float result = (float) input;
if (float.IsPositiveInfinity(result))
{
result = float.MaxValue;
} else if (float.IsNegativeInfinity(result))
{
result = float.MinValue;
}
Ответ 2
Вы можете использовать метод .NET Convert.ToSingle()
. Например:
float newValue = Convert.ToSingle(value);
В соответствии с Документация MSDN:
Преобразует указанное значение в число с плавающей запятой с одной точностью.
Update:
После дальнейшего рассмотрения Convert.ToSingle(Double.MaxValue)
приводит к бесконечности, поэтому вам все равно придется проверять бесконечность, как это сделано в ответе Джона Скита.
Ответ 3
Если результат вычисления вычисления превышает диапазон типа, в котором вы его храните, необходимо сделать одну из трех вещей:
- Выбросить исключение
- Возвращает значение "дозорного", которое указывает на наличие проблемы и которое предпочтительно будет признано как эффективное аннулирование любых вычислений там, где оно появляется
- Привести результат к определенному значению (к которому он будет привязан даже если он не превышает диапазон вашего числового типа). Например, может быть узел датчика с двумя усредненными по времени входами X и Y, чье "значение" равно (X * X)/(Y * Y) - (Y * Y)/(X * X). Если входные сигналы являются шумными, низкое значение на одном входе может считаться исключительно низким значением. Если измерение будет использоваться для управления контуром обратной связи, и если "фактическое" значение не будет превышать +/- 1000000,0, может быть лучше привязать значение к этому диапазону, чем позволить контуру управления видеть полностью дикую вычисленную (X или Y - наименьшее возможное ненулевое значение).
Существует много приложений, в которых третий подход будет правильным. В таких ситуациях, однако, если было бы целесообразно привязать показания к значению миллиона, то не имеет значения, приводит ли вычисление значение 1000,001 или 1E + 39 (с плавающей запятой + INF). В обоих случаях нужно привязать к миллиону.
Ответ 4
Используйте эту функцию
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);
}