Всегда ли double 0.0 представлен точно в переносимом C? - PullRequest
2 голосов
/ 15 апреля 2011

Можно ли ожидать, что следующий код будет работать в всех средах, в которых имеется ANSI-совместимый компилятор C?

double n = 0;
assert(n == 0);

А как насчет C ++?

Ответы [ 4 ]

5 голосов
/ 15 апреля 2011

Стандарт C накладывает некоторые ограничения на представление значений с плавающей запятой. В §5.2.4.2.2 Характеристики плавающих типов числа с плавающей запятой должны демонстрировать характеристики, как если бы они были определены моделью:

x = sb e Σ k = 1..p f k b -k

Где:

  • с является знаком и должно быть ± 1;
  • b является основанием и должно быть целым числом> 1;
  • e - показатель степени, который должен быть целым числом от e min до e max ;
  • p - точность; и
  • f k - неотрицательные целые числа <<strong> b - цифры значимого и.

В этой модели ноль всегда может быть точно представлен - просто требуется, чтобы все цифры и цифры f k были равны нулю.

Учитывая следующее ограничение в §6.3.1.4:

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

Отсюда следует, что ноль всегда должен быть неизменным при преобразовании из целого числа 0 в тип с плавающей запятой. Поэтому утверждение должно всегда выполняться.

5 голосов
/ 15 апреля 2011

Вы не спрашиваете, всегда ли 0.0 представляется точно.

В выражении assert(n == 0), 0 преобразуется в double до того, как произойдет сравнение.Таким образом, утверждение может быть запущено только в том случае, если преобразование 0 из int в double не воспроизводимо.Это гораздо более слабое ограничение, чем то, о чем вы спрашиваете, и оно почти наверняка будет иметь место (хотя я не могу придумать ссылку на стандарты, которая бы гарантировала это на моей голове).

К вопросувы намеревались спросить:

Как уже упоминалось, стандарт C не требует, чтобы типы с плавающей запятой отображались на IEEE-754, но я не знаю ни одного представления с плавающей запятой, используемого с любым компилятором C, который делаетне имеют точного представления ноль.Тем не менее, было бы «законно» для реализации C использовать формат для double, который не имеет точного нуля.

2 голосов
/ 15 апреля 2011

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

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

1 голос
/ 15 апреля 2011

C99 не требует IEEE754, только рекомендует.Существует символ, который могут определять платформы компиляции, соответствующие IEEE 754 (Приложение F).Если компилятор определяет этот символ, тогда да, утверждение будет гарантированно выполнено.Когда литеральная константа представляется точно как число с плавающей запятой, тогда это число с плавающей запятой - это то, что вы должны получить в скомпилированной программе.

Я не могу представить себе какую-либо не-IEEE 754 систему с плавающей запятой, котораяне будет иметь ноль или причину не отображать литерал 0 в исходном коде на него.

...