2010-12-11 2 views
2

Расчеты с плавающей запятой, которые используют постоянные целые числа времени компиляции, выполняемые во время компиляции или во время выполнения? Например, когда операция деления вычисляется:Арифметика с плавающей точкой во время компиляции

template <int A, int B> 
inline float fraction() 
{ 
    return static_cast<float>(A)/B; 
} 
+3

AFAIK стандарт не определяет это, и это зависит от флагов компилятора и оптимизации. – khachik

+1

BTW, не забывайте, что вы можете проверить выход ассемблера своего компилятора. Вы спрашиваете о специфике компилятора, а не о языке. Моя ставка заключается в том, что хороший компилятор (особенно с оптимизацией) рассчитает во время компиляции все, что может. – Kos

ответ

1

Я считаю, что это реализация определена, но большинство компиляторов будет оценивать постоянные выражения во время компиляции. Однако, даже если у вас не следующие модификации:

template <int A, int B> 
inline float fraction() 
{ 
    static const float f = static_cast<float>(A)/B; 
    return f ; 
} 

, по крайней мере убедиться, что выражение вычисляется только один раз, если оно вычисляется во время выполнения.

1

Лучше всего смотреть на сгенерированный код - нет никакой гарантии, что операции с плавающей точкой будет выполняться во время компиляции, но на более высоких уровнях оптимизации они могли бы быть, в частности, для чего-то простого подобного.

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

2

Для чего-то такого простого, компилятор будет возможно сделать это во время компиляции. Фактически, компилятор, вероятно, сделает это во время компиляции даже без шаблонов, если все значения известны во время компиляции: т. Е. Если у нас есть inline float fraction(int A, int B), он, вероятно, сделает деление во время компиляции, если мы позвоним fraction(1,2).

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

// Something similarly simple that doesn't use floating-point ;) 
template <int A, int B> 
struct Product { 
    enum { value = A * B }; 
}; 

// Later: 
... Product<3, 4>::value ... 
1

Вы должны ждать GCC 4.6 с реализацией constexpr ключевого слова C++ 0x.

+1

И пока мы ждем, и каждый другой компилятор просто игнорирует C++ 0x и * if * он когда-либо получает ратификацию, как мы должны работать? ;) – Clifford

1

Ни стандарты C или C++ требуют, что постоянные выражения любой полосы оценивается во время компиляции, но они не позволяют его. Большинство компиляторов, выпущенных за последние 20 лет, будут оценивать арифметические выражения, поэтому, если не выполнять вызов функции или встраивать код, важно, чтобы это было так просто, как posble.

Если объем этих выражений ограничен одним файлом, вы всегда можете воспользоваться препроцессором и #define FRACTION(a,b) (float(a)/float(b)) для удобства. Я не рекомендую делать это в заголовке, если у вас нет хорошей схемы предотвращения заражения любого файла, который #include.

Смежные вопросы