Должен ли C вычислять число в экспоненциальном представлении?

Максимальное значение числа с плавающей запятой равно 3,40282347E+38. Это эквивалентно 3,40282347 * 10^38. Мне интересно, если я установлю число с плавающей запятой, равным этому, должно ли оно фактически выполнять мощность и умножение, чтобы получить значение для хранения, или научная запись просто фактическое значение?

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


person FLOWMEEN    schedule 12.04.2016    source источник
comment
Литеральные константы, подобные этой, оцениваются во время компиляции, а не во время выполнения. Кроме того, используйте FLT_MAX вместо жестко заданной константы.   -  person Paul R    schedule 12.04.2016
comment
хорошо, здорово знать. мне не разрешено включать заголовок float.h, поэтому я не могу использовать FLT_MAX   -  person FLOWMEEN    schedule 12.04.2016
comment
Это также может помочь: stackoverflow.com/questions/3271588/   -  person RhinoDevel    schedule 12.04.2016
comment
Не могу включить float.h... эти причудливые правила для домашних заданий иногда заставляют меня сомневаться в том, что происходит обучение... Я могу понять, говоря людям не включать <unordered_map>, если задание заключается в реализации хэш-таблицы, но это нелепо.   -  person Dietrich Epp    schedule 12.04.2016
comment
@DietrichEpp Я предполагаю, что некоторые из наиболее странных правил предназначены для предотвращения прямого использования загруженного программного обеспечения в качестве ответов на домашнее задание.   -  person Patricia Shanahan    schedule 12.04.2016


Ответы (3)


Когда вы используете литералы в своем исходном коде, эти литералы (и в основном выражения, содержащие все литералы для свертывания констант) оцениваются во время компиляции и преобразуются в такие инструкции, как move immediate, add immediate, move special_constant_register и т. д.

Например:

int a = 10, b = 0xA;

Здесь литералы 10 и 0xA оцениваются как одно и то же значение во время компиляции. В вашем случае также double literal или float literal будет оцениваться во время компиляции, и наиболее подходящее значение будет присвоено переменной.

person Mohit Jain    schedule 12.04.2016

Когда вы пишете 3.4e38, он полностью оценивается во время компиляции.

Когда вы пишете 3.4 * 10^38, вы получаете совершенно неожиданный результат. Это потому, что ^ не означает степень в C. Это означает «исключающее или», а 10 ^ 38 == 44. А может, он вообще не компилируется, потому что оценивается как (3.4 * 10) ^ 38, а xor не определен для плавающих точек. Или он определен, так что это будет 340 ^ 10.

person Roland Illig    schedule 12.04.2016
comment
спасибо, это был просто псевдокод. Я имел в виду 3,40282347 * pow(10, 38) - person FLOWMEEN; 12.04.2016

Все это делается во время компиляции. Следующий код...

#include <float.h>
#include <stdio.h>
#include <stdlib.h>
int main(void) {
  float foo = 3.40282347E+38;
  float bar = 3.40282347e38;
  printf("foo=%g\nbar=%g\n", foo, bar);
  return 0;
}

Производит это на ассемблере. Чтобы получить ассемблер, используйте флаг -S для gcc, т.е. что-то вроде

gcc -S -Wall -O3 -pedantic -std=c11 scientific_notation.c 

Это использование лязга. Немного поковыряю ассемблер...

 .section  __TEXT,__text,regular,pure_instructions
  .macosx_version_min 10, 11
  .section  __TEXT,__literal8,8byte_literals
  .align  3
LCPI0_0:
  .quad 5183643170566569984     ## double 3.4028234663852886E+38
  .section  __TEXT,__text,regular,pure_instructions
  .globl  _main
  .align  4, 0x90

... отрезал.

Обратите внимание на эту строку .quad 5183643170566569984. Это константа. Также обратите внимание, что хотя у меня есть две из этих констант в моем коде, только одна нужна компилятору.

person Harry    schedule 12.04.2016