Преобразование поплавка в двойной - PullRequest
8 голосов
/ 14 сентября 2009

Сколько стоит конвертация float в double? Это так же банально, как преобразование int в long?

РЕДАКТИРОВАТЬ: я предполагаю, что платформа, где float составляет 4 байта, а double это 8 байтов

Ответы [ 6 ]

10 голосов
/ 14 сентября 2009

Особенности платформы

Это зависит от платформы, используемой для вычисления с плавающей точкой. С x87 FPU преобразование бесплатное, так как содержимое регистра такое же - единственная цена, которую вы иногда можете заплатить, это трафик памяти, но во многих случаях даже нет трафика, так как вы можете просто использовать значение без какого-либо преобразования. x87 на самом деле странный зверь в этом отношении - трудно правильно различить числа с плавающей запятой и двойники на нем, поскольку используемые инструкции и регистры одинаковы, отличаются то, что являются инструкциями загрузки / сохранения, а сама точность вычислений контролируется с помощью битов состояния , Использование смешанных вычислений с плавающей запятой / двойных может привести к непредвиденным результатам (и из-за этого есть опции командной строки компилятора для управления точным поведением и стратегиями оптимизации).

Когда вы используете SSE (а иногда Visual Studio использует SSE по умолчанию), оно может отличаться, так как вам может потребоваться передать значение в регистрах FPU или сделать что-то явное для выполнения преобразования.

Экономия памяти

В качестве резюме и ответа на ваш комментарий в другом месте: если вы хотите сохранить результаты плавающих вычислений в хранилище 32b, результат будет такой же скорости или быстрее, потому что:

  • Если вы сделаете это на x87, преобразование будет бесплатным - единственная разница будет в том, что вместо fstp qword будет использоваться fstp dword [].
  • Если вы сделаете это с включенным SSE, вы можете даже увидеть некоторое повышение производительности, так как некоторые вычисления с плавающей запятой могут быть выполнены с SSE, если точность вычислений равна только плавающей запятой вместо значения по умолчанию double.
  • Во всех случаях трафик памяти ниже
5 голосов
/ 14 сентября 2009

Преобразования с плавающей точкой в ​​двойные происходят бесплатно на некоторых платформах (PPC, x86, если ваш компилятор / среда выполнения использует "к черту" с тем типом, который вы мне сказали использовать, я все равно буду оценивать все в long double, ня ня «Режим оценки).

В среде x86, где оценка с плавающей запятой фактически выполняется в указанном типе с использованием регистров SSE, преобразования между числами с плавающей запятой и двойными являются примерно такими же дорогими, как сложение или умножение с плавающей запятой (т. Е. Вряд ли будет учитываться производительность вы делаете много из них).

Во встроенной среде, в которой отсутствует аппаратная плавающая точка, они могут быть несколько дорогостоящими.

0 голосов
/ 07 мая 2016

Может быть, это поможет:

#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;
}
0 голосов
/ 14 сентября 2009

Я не могу себе представить, что это будет намного сложнее. Большая разница между преобразованием int в long и преобразованием float в double заключается в том, что типы int имеют два компонента (знак и значение), а числа с плавающей запятой имеют три компонента (знак, мантисса и экспонента).

Кодировка IEEE 754 одинарной точности в 32 битах, используя 1 бит для знака, 8 биты для показателя степени и 23 бита для Значение и. Тем не менее, он использует скрытый бит, поэтому значение равно 24 биты (р = 24), хотя это кодируется с использованием только 23 бит.

- Дэвид Голдберг, Что должен знать каждый компьютерщик об арифметике с плавающей точкой

Таким образом, при преобразовании между float и double будет сохраняться один и тот же знаковый бит, установите последние 23/24 бита мантиссы плавающего в мантиссу двойного и установите последние 8 битов экспоненты поплавка в показателе двойного.

Такое поведение может быть гарантировано IEEE 754 ... Я не проверял это, поэтому я не уверен.

0 голосов
/ 14 сентября 2009

Это относится к используемой вами реализации C ++. В C ++ типом с плавающей точкой по умолчанию является double . Компилятор должен выдать предупреждение для следующего кода:

float a = 3.45;

потому что двойное значение 3,45 присваивается поплавку. Если вам нужно использовать float, добавьте суффикс к f :

float a = 3.45f;

Дело в том, что все числа с плавающей точкой по умолчанию double . Безопасно придерживаться этого значения по умолчанию, если вы не уверены в деталях реализации вашего компилятора и не имеете достаточного понимания вычислений с плавающей запятой. Избегайте актерского состава.

Также см. Раздел 4.5 из Язык программирования C ++ .

0 голосов
/ 14 сентября 2009

вероятно, немного медленнее, чем преобразование int в long, так как требуемая память больше и манипулирование более сложным. Хорошая справка о проблемах с выравниванием памяти

...