FLT_HAS_SUBNORM равен 0: приводит ли построенная вручную субнормаль к четко определенному поведению при использовании такой субнормальности?

В случае, если FLT_HAS_SUBNORM равно 0: приводит ли построенная вручную (например, с помощью каламбура через union или использование memcpy()) субнормаль к четко определенному поведению, когда такая субнормаль используется в качестве входных данных для операций FP (например, сравнения FP)?

Пример:

#include <stdio.h>
#include <float.h>
int main( void )
{
    union { unsigned int i; float f; } u = { .i = 1 }; // subnormal
    printf("%d %d %a 0x%08lx\n", FLT_HAS_SUBNORM, u.f != 0.0f, u.f, u.i);
    return 0;
}

Выход:

лязг: 1 1 0x1p-149 0x00000001

гкк: 1 1 0x1p-149 0x00000001

тестовый компилятор: 0 1 0x0p+0 0x00000001

Примечание: здесь мы видим, что тестовый компилятор не поддерживает %a для субнормальных значений (что объясняется тем, что / коррелирует с FLT_HAS_SUBNORM равным 0).

Вопросы:

  1. Приводит ли здесь u.f != 0 к четко определенному поведению?
  2. Если это так, то почему стандарт C разрешает такие построенные вручную субнормаль (а также операции FP с такими вручную построенными субнормальми, приводящие к результатам, совместимым с IEEE 754), если FLT_HAS_SUBNORM равно 0?

УПД. Я читал стандарт. Я в замешательстве, потому что там написано:

FLT_HAS_SUBNORM равно 0 означает, что subnormal numbers are absent (type does not support subnormal numbers)

Однако, несмотря на type does not support subnormal numbers, в приведенном выше примере мы видели, что можно вручную построить субнормаль и выполнить над ними некоторые операции FP, получая результаты, соответствующие стандарту IEEE 754.

УПД. Другими словами: следует ли интерпретировать приведенный выше пример (u.f != 0.0f) как нарушение FLT_HAS_SUBNORM is 0? Если это так, то, пожалуйста, докажите это.

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

EOF 14.12.2020 22:00

pmor, почему ты считаешь u.f субнормальным? fabsf(u.f) < FLT_MIN && u.f != 0 будет лучшим тестом. Опубликуйте его значение с помощью "%a".

chux - Reinstate Monica 14.12.2020 22:03

@chux-ReinstateMonica Опубликовано (и %a, и 0x%08lx).

pmor 14.12.2020 22:13

Ваш вывод соответствует системе с прямым порядком байтов, где int больше, чем float. Вы не продемонстрировали способность «вручную конструировать субнормаль». Вы также не продемонстрировали, что можете «выполнять над ними некоторые операции FP».

user3386109 14.12.2020 22:18

Возможно, что значение u.f просто недействительно или интерпретируется непоследовательно. Таким образом, его печать или сравнение с 0,0 недостаточно убедительны в отношении его ценности. Возможно, напечатав его как printf("%a\n", u.f * powf(2, 100));, можно вывести 0x1p-49 или какое-то близкое значение, и поэтому мы сможем вывести u.f. В конце концов, это выглядит просто UB, как ответил .

chux - Reinstate Monica 14.12.2020 22:38

@chux-ReinstateMonica Убедитесь, что gcc, clang и cl (msvc) создают .exe, который печатает 0x1p-49.

pmor 15.12.2020 01:16

Я подозреваю, что в вашем cl искусственное субнормальное значение может оцениваться для большей части математики как ожидаемое субнормальное значение. Однако для печати double to text может просто принимать любые субнормальные значения и нули (все они имеют экспоненту со смещением 0) и печатать ноль, используя преимущество того, что субнормальные значения не встречаются.

chux - Reinstate Monica 15.12.2020 01:33
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
7
82
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Приводит ли здесь u.f != 0 к четко определенному поведению?

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

Если это так, то почему стандарт C разрешает создавать такие субнормальы вручную…

C является языком низкого уровня и обеспечивает прямой доступ к байтам, представляющим любой объект. Вы также можете создавать представления целых чисел, которые недействительны из-за ошибок четности (в реализациях, которые имеют такие) и представления объектов char, которые не находятся в определенном наборе символов. Вы также можете возиться с байтами FILE или struct tm и создавать объекты с неподдерживаемыми значениями. Тот факт, что вы можете манипулировать байтами, не означает, что любые манипуляции с байтами приводят к допустимому или поддерживаемому значению.

Спасибо за ответ. Можете ли вы доказать (ссылаясь на стандарт, используя proof by contradiction, другими способами), что no? P.S. Я тоже склоняюсь к тому, что no, но доказать пока не могу.

pmor 14.12.2020 22:19

@pmor: C 2018 4 2: «… Неопределенное поведение иначе обозначено в этом документе… отсутствием какого-либо явного определения поведения…»

Eric Postpischil 14.12.2020 22:22

В какой именно момент происходит УБ? В момент manual constriction (каламбур типа, memcpy(), чтение из файла и т.д.) или в момент выполнения операции FP, которая принимает на вход такие вручную сжатые floating-point object(s)?

pmor 14.12.2020 23:23

Вопрос про Characterization as absent .. from non-subnormal inputs, .... Требуя from non-subnormal inputs, что именно подразумевает стандарт: тот факт, что subnormal inputs do not exist in this 'absent' characterization (и, следовательно, не может быть построен с помощью каламбура типов, memcpy(), чтения из файла и т. д.) или тот факт, что subnormal inputs may exist, but in this case some FP operations may produce subnormal results (вывод из «отсутствующей» характеристики)?

pmor 14.12.2020 23:39

@pmor: запись байтов в память объекта имеет определенное поведение. Чтение значения объекта, байты которого не являются представлением некоторого значения в типе объекта, имеет неопределенное поведение.

Eric Postpischil 15.12.2020 00:18

@pmor: в этой сноске говорится, что если реализация имеет субнормальные значения в своем типе float, но они никогда не создаются операциями с нормальными операндами, эта реализация должна определить FLT_HAS_SUBNORM как 0. Это в дополнение к тому факту, что реализации, которые не имеют субнормальные значения в его типе float должны определять FLT_HAS_SUBNORM как 0. Таким образом, если FLT_HAS_SUBNORM равно 0, вы не можете сделать вывод, не имеет ли реализация субнормальных значений в своем типе или они есть, но они не могут быть получены из нормальных операндов.

Eric Postpischil 15.12.2020 00:20

Да, все, что говорит стандарт, это то, что If FLT_HAS_SUBNORM is 0, then any_normal <op> any_normal never produces subnormal недостаточно, чтобы ответить на все вопросы о FLT_HAS_SUBNORM is 0. Можете ли вы добавить к вашему ответу, что UB происходит именно в момент выполнения операции FP, которая принимает в качестве входных данных такие суженные вручную объекты с плавающей запятой (а не в момент ручного построения таких объектов с плавающей запятой). ))?

pmor 15.12.2020 16:17

Другие вопросы по теме

Упаковка 16-битного числа с плавающей запятой IEEE-754 в 16-битное целое число без знака с сохранением порядка
Как отключить печать «-nan» из fmt
Является ли это ожидаемым поведением для плавающего слияния-умножения-добавления?
Получите представление одинарной точности IEEE-754 действительного числа в VHDL
Что вызывает это арифметическое несоответствие между numpy и MATLAB и как я могу заставить любое поведение в Python?
Неожиданное круглое поведение Numpy float32
Должны ли две программы, скомпилированные с параметрами -O0 и -O2, давать одинаковые результаты с плавающей запятой?
Гарантируется ли, что деление на степень 10 дает точный результат в стандарте арифметики с плавающей запятой)?
Числа с плавающей запятой на машине VAX
Когда умножить относительно большое значение с плавающей запятой на два относительно небольших значения с плавающей запятой, каков наилучший порядок арифметики для устранения ошибки