Преобразование float в double
-
07-07-2019 - |
Вопрос
Насколько дорогостоящим является преобразование float
к a double
?Является ли это таким же тривиальным, как int
Для long
обращение?
Редактировать:Я предполагаю платформу, где значение float равно 4 байтам, а double - 8 байтам
Решение
Соображения о платформе
Это зависит от платформы, используемой для вычисления float.В x87 FPU преобразование бесплатное, поскольку содержимое регистра остается тем же - единственная цена, которую вы иногда можете заплатить, - это трафик памяти, но во многих случаях трафика даже нет, поскольку вы можете просто использовать значение без какого-либо преобразования.x87 на самом деле странный зверь в этом отношении - на нем трудно правильно различить значения с плавающей точкой и удвоения, поскольку используемые инструкции и регистры одинаковы, отличаются инструкции загрузки / сохранения, а сама точность вычислений контролируется с помощью битов состояния.Использование смешанных вычислений с плавающей запятой / double может привести к неожиданным результатам (и из-за этого существуют параметры командной строки компилятора для управления точным поведением и стратегиями оптимизации).
Когда вы используете SSE (а иногда Visual Studio использует SSE по умолчанию), это может отличаться, так как вам может потребоваться перенести значение в регистры FPU или сделать что-то явное для выполнения преобразования.
Производительность при экономии памяти
В качестве резюме и ответа на ваш комментарий в другом месте:если вы хотите сохранить результаты плавающих вычислений в хранилище объемом 32 Б, результат будет таким же или быстрее, потому что:
- Если вы сделаете это на x87, преобразование будет бесплатным - единственное отличие будет заключаться в том, что вместо fstp qword[] будет использоваться fstp dword.
- Если вы сделаете это с включенным SSE, вы можете даже увидеть некоторый прирост производительности, поскольку некоторые вычисления с плавающей запятой могут быть выполнены с помощью SSE, если точность вычислений равна только float вместо double по умолчанию.
- Во всех случаях объем памяти меньше
Другие советы
Преобразования с плавающей запятой в double выполняются бесплатно на некоторых платформах (PPC, x86, если ваш компилятор / среда выполнения использует режим оценки "к черту тот тип, который вы мне сказали использовать, я все равно собираюсь оценить все в режиме long double, ня-ня-ня").
В среде x86, где вычисление с плавающей запятой фактически выполняется в указанном типе с использованием регистров SSE, преобразования между float и double примерно такие же дорогие, как сложение или умножение с плавающей запятой (т. Е. вряд ли будут учитываться с точки зрения производительности, если вы не выполняете очень много из них).
Во встроенной среде, где отсутствует аппаратная система с плавающей запятой, они могут быть несколько дорогостоящими.
Это относится к используемой вами реализации C ++. В C ++ типом с плавающей точкой по умолчанию является double . Компилятор должен выдать предупреждение для следующего кода:
float a = 3.45;
потому что двойному значению 3.45 присваивается значение с плавающей точкой. Если вам нужно использовать float, добавьте суффикс к значению f :
float a = 3.45f;
Дело в том, что все числа с плавающей запятой по умолчанию double . Безопасно придерживаться этого значения по умолчанию, если вы не уверены в деталях реализации вашего компилятора и не имеете достаточного понимания вычислений с плавающей запятой. Избегайте актеров.
См. также раздел 4.5 в языке программирования C ++ . р>
Я не могу себе представить, что это будет намного сложнее. Большая разница между преобразованием int в long и преобразованием float в double заключается в том, что типы int имеют два компонента (знак и значение), а числа с плавающей запятой имеют три компонента (знак, мантисса и экспонента).
IEEE 754 с одинарной точностью кодируется в 32 битах, используя 1 бит для знака, 8 биты для показателя степени и 23 бита для Значение и. Тем не менее, он использует скрытый бит, поэтому значение равно 24 биты (р = 24), хотя это кодируется с использованием только 23 битов.
- Дэвид Голдберг, Что должен знать каждый учёный-компьютерщик с плавающей точкой Арифметика
Таким образом, преобразование между float и double будет сохранять один и тот же знаковый бит, установите последние 23/24 бита мантиссы float в мантиссу двойного и установите последние 8 бит экспоненты float в показателе double. р>
Такое поведение может быть гарантировано даже IEEE 754 ... у меня нет проверил, так что я не уверен.
вероятно немного медленнее, чем преобразование int в long, так как требуемая память больше и манипулирование более сложным. Хорошая справка о проблем с выравниванием памяти
Может быть, это поможет:
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
double _ftod(float fValue)
{
char czDummy[30];
printf(czDummy,"%9.5f",fValue);
double dValue = strtod(czDummy,NULL);
return dValue;
}
int main(int argc, char* argv[])
{
float fValue(250.84f);
double dValue = _ftod(fValue);//good conversion
double dValue2 = fValue;//wrong conversion
printf("%f\n",dValue);//250.840000
printf("%f\n",dValue2);//250.839996
getch();
return 0;
}