Неопределенность типа данных с плавающей точкой

Я делаю численный анализ математического программного обеспечения, которое я разработал. Я хочу определить, в чем заключается неопределенность моего результата. бытие f() мой метод и x входное значение, я хочу идентифицировать y моего результата как f(x) +/- y, мой f() Метод имеет несколько операций между float переменные. Чтобы изучить распространение ошибки произошло в f()Я должен применить формулы статистического распространения неопределенности, и для этого я должен знать неопределенность float переменная.

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

Из того, что я понял из литературы, FLT_EPSILON макрос в http://www.cplusplus.com/reference/cfloat/ определяет мой y значение, но этот быстрый тест доказывает, что это неправильно:

float f1 = 1.234567f;
float f2 = 1.234567f + 1.192092896e-7f;
float f3 = 1.234567f + 1.192092895e-7f;

printf("Inicial:\t%f\n", f1);
printf("Inicial:\t%f\n", f2);
printf("Inicial:\t%f\n\n", f3);

Выход:

Inicial:  1.234567
Inicial:  1.234567
Inicial:  1.234567

Когда ожидаемый результат должен быть:

Inicial:  1.234567
Inicial:  1.234568 <---
Inicial:  1.234567

В чем я не прав? Не должен float ценность x + FLT_EPSILON а также x - FLT_EPSILON быть таким же?

РЕДАКТИРОВАТЬ: мой вопрос R float ценность x, что y ценить это x + y || x - y равняется тому же Rfloat значение?

3 ответа

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

FLT_EPSILON не является мерой неопределенности или ошибки в результатах с плавающей точкой. Это расстояние между 1 и следующим значением, представляемым в float тип. Следовательно, это размер шагов между представимыми числами на величину 1.

Когда вы преобразуете десятичное число в число с плавающей запятой, полученная ошибка округления может иметь величину до 1/2 размера шага при использовании общего режима округления до ближайшего. Причина, по которой граница равна ½ размера шага, заключается в том, что для любого числа x (в пределах конечной области формата с плавающей запятой) существует представимое значение в пределах ½ размера шага (включительно). Это связано с тем, что если представимое число больше 1/2 размера шага в одном направлении, то представимое число меньше 1/2 размера шага в другом направлении.

Размер шага зависит от величины чисел. С двоичной переменной с плавающей точкой она удваивается в 2, и снова в 4, затем в 8 и так далее. Ниже 1 он делится пополам, и снова на ½, ¼ и так далее.

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

Две цифры, используемые в вашем примере кода, 1.192092897e-7f а также 1.192092896e-7f, настолько близко друг к другу, что они превращаются в одно и то же float значение 2−23. Вот почему нет разницы в вашем f2 а также f3,

Есть разница между f1 а также f2, но вы не напечатали достаточно цифр, чтобы отобразить его.

Вы спрашиваете: "Не должен ли float ценность x + FLT_EPSILON а также x - FLT_EPSILON быть таким же? ", но ваш код не содержит x - FLT_EPSILON,

Re: "Мой вопрос R значение с плавающей запятой x, что y ценить это x + y || x - y равняется тому же R значение с плавающей запятой? " y = 0. Вы хотели спросить, какое наибольшее значение y что удовлетворяет условию? Это немного сложно.

Размер шага для числа x называется ULP of x, который мы можем рассматривать как функцию ULP (x). ULP выступает за единицу наименьшей точности. Это значение места наименьшей цифры в представлении с плавающей запятой для x. Это не константа; это функция х.

Для большинства значений, представляемых в формате с плавающей запятой, наибольшее y то, что удовлетворяет вашему условию, равно ½ ULP (x) наименьшей цифры в представлении с плавающей запятой x и является четным, а если цифра нечетная, оно составляет чуть меньше ½ ULP (x). Эта сложность возникает из-за правила, согласно которому результаты арифметики округляются до ближайшего представимого значения, и в случае связи выбирается значение с четной младшей цифрой. Таким образом, добавление ½ ULP (x) к x приведет к равенству, которое округляется до x, если младшая цифра четная, но не округляется до x, если младшая цифра нечетная.

Однако для х, которые находятся на границе, где меняется ULP, наибольшее y что удовлетворяет вашему условию ¼ ULP(x). Это происходит потому, что чуть ниже x (по величине) размер шага изменяется, и следующее число, меньшее x, равно половине шага x вместо обычного полного размера шага. Таким образом, вы можете пройти только половину к этому значению, прежде чем изменить результат вычитания, поэтому наиболее y может быть ¼ ULP(х).

float f1 = 1.234567f;
float f2 = f1 + 1.192092897e-7f;
float f3 = f1 + 1.192092896e-7f;

printf("Inicial:\t%.20f\n", f1);
printf("Inicial:\t%.20f\n", f2);
printf("Inicial:\t%.20f\n\n", f3);

Выход:

Inicial:        1.23456704616546630000
Inicial:        1.23456716537475590000
Inicial:        1.23456716537475590000

Нет, ваши ожидания неверны
Во-первых printf вызов, вы печатаете переменную f1 без эффекта, который просто 1.234567f,

Float является 32 бит IEEE 754 с плавающей запятой одинарной точности: 1 немного за знак, 8 биты для показателя степени и 23* для значения, то есть float имеет 7 десятичные цифры точности.

Увеличить printf количество напечатанных цифр, чтобы увидеть больше, но после 7 цифры его просто шум:

#include <stdio.h>

int main(void) {

 float f1 = 1.234567f;
 float f2 = 1.234567f + 1.192092897e-7f;
 float f3 = 1.234567f + 1.192092896e-7f;

 printf("Inicial:\t%.16f\n", f1);
 printf("Inicial:\t%.16f\n", f2);
 printf("Inicial:\t%.16f\n\n", f3);

 return 0;
}

Выход:

Inicial:        1.2345670461654663                                                                                                           
Inicial:        1.2345671653747559                                                                                                           
Inicial:        1.2345671653747559 
Другие вопросы по тегам