Y_P>выдает такие результаты
Y_P>1.99999999999999980000
Y_P>2.00000000000000000000
Если хочешь, чтобы результаты были одинаковые — используй опцию компиляции /Op (Improve Float Consistency)
Из MSDN:
This option improves the consistency of floating-point tests for equality and inequality by disabling optimizations that could change the precision of floating-point calculations.
By default, the compiler uses the coprocessor's 80-bit registers to hold the intermediate results of floating-point calculations. This increases program speed and decreases program size. However, because the calculation involves floating-point data types that are represented in memory by less than 80 bits, carrying the extra bits of precision (80 bits minus the number of bits in a smaller floating-point type) through a lengthy calculation can produce inconsistent results.
With /Op, the compiler loads data from memory prior to each floating-point operation and, if assignment occurs, writes the results back to memory upon completion. Loading the data prior to each operation guarantees that the data does not retain any significance greater than the capacity of its type.
A program compiled with /Op may be slower and larger than one compiled without /Op.
Здравствуйте, HiFix, Вы писали:
HF>Почитай про правила операций над числами с плавающей точкой, например здесь
Нисагласен.
Тут гораздо интересней, что результат разный в одинаковых строчках.
Правильно работающая программа — просто частный случай Undefined Behavior
Здравствуйте, _Winnie, Вы писали: _W>Нисагласен.
С чем? _W>Тут гораздо интересней, что результат разный в одинаковых строчках.
Действительно интересно VC7.1 в дебаге выдает в обоих случаях 2.00000, а в релизе 1.99999999999999980000. Причем 1.99 он выдает только в первом случае, а во втором, третьем, десятом 2.00. Надо самому еще раз про floating-point operations почитать .
... << RSDN@Home ...и тишина... а по бокам мертвые с косами стоят...
_W>Ниверю. _W>Что именно этот.
Именно этот код. Сам только что проверял. _W>Какой компилятор/платформа/настройки.
Платформа Win32, компилятор VC7.1, релиз (в дебаг все нормально).
... << RSDN@Home ...и тишина... а по бокам мертвые с косами стоят...
Все, что здесь сказано, может и будет использоваться против меня...
Re: Что за хрень творится (math.h)
От:
Аноним
Дата:
13.10.06 03:36
Оценка:
Вполне возможная вещь. Числа с плавающей точкой вообще очень копризные.
У меня однажды в 6 была такая ситуация. На каждом шаге цикла с double переменной
прибавляется 0.1. Всё было замечательно, но на одном шаге он почемуто не прибавлял.
Не помню какое это было число. Но получил я его только со второго раза.
По этому стараюсь точную инфу хранить в целых числах.
Здравствуйте, Silent Bob, Вы писали:
SB>Это printf шалит.
Не знаю, считать ли это шалостью. Вычисления зависят от необнулённых флагов FPU, которые отличаются
double a = .....;
// здесьdouble b = .....;
// иdouble a = .....;
printf("%.20f\n", a); // внутри тоже пользуется плавающей арифметикой - для перевода double в десятичный вид
// здесьdouble b = .....;
Здравствуйте, Yozh_Programmer, Вы писали:
Y_P>Почему этот код выдает такие результаты Y_P>1.99999999999999980000 Y_P>2.00000000000000000000
Такое поведение является абсолютно нормальным (в том смысле, что его допускают все имеющие отношение к теме стандарты). Причин такому фокусу может быть мильон и вот одна из них.
Процессор умеет представлять вещественные числа в 80-битном формате. А вот если они выгружаются в память, то число будет усечено до 64 бит. Результат расчета зависит от того, было ли число сохранено и потом получено из памяти, или все вычисления были проделаны с привлечением только регистров процессора.
Где в твоей программе имеет место этот эффект и он ли это -- можно только гадать (или посмотреть ассемблерный листинг). Скорее всего, чудо случается при подготовке результирующей строчки в printf.
Тот, кто желает, но не делает, распространяет чуму.
Здравствуйте, volk, Вы писали:
V>Здравствуйте, Yozh_Programmer, Вы писали:
Y_P>>Почему этот код выдает такие результаты Y_P>>1.99999999999999980000 Y_P>>2.00000000000000000000
V>Такое поведение является абсолютно нормальным (в том смысле, что его допускают все имеющие отношение к теме стандарты). Причин такому фокусу может быть мильон и вот одна из них.
V>Процессор умеет представлять вещественные числа в 80-битном формате. А вот если они выгружаются в память, то число будет усечено до 64 бит. Результат расчета зависит от того, было ли число сохранено и потом получено из памяти, или все вычисления были проделаны с привлечением только регистров процессора.
V>Где в твоей программе имеет место этот эффект и он ли это -- можно только гадать (или посмотреть ассемблерный листинг). Скорее всего, чудо случается при подготовке результирующей строчки в printf.
В связи с этим можно ли проблему свалить на оптимизацию?: В первый раз значение вычисляется, затем сливается в память, так как такой код встретиться снова, и следующий раз, вместо того, чтобы вычислять — просто загружает из памяти, но там уже урезанный до 64 бит результат.
Предпочитаю Виртуалу Реал. В Реале люблю Реальных Девушек.
Здравствуйте, Thermal, Вы писали:
T>В связи с этим можно ли проблему свалить на оптимизацию?: В первый раз значение вычисляется, затем сливается в память, так как такой код встретиться снова, и следующий раз, вместо того, чтобы вычислять — просто загружает из памяти, но там уже урезанный до 64 бит результат.
Конечно нельзя. Тот сценарий, который я здесь привел -- это всего лишь одна из возможных причин. Кроме нее здесь еще упоминали сборс состояния сопроцессора при системных вызовах. Кажется, бывает еще нечто, что приводит к тому же эффекту -- сходу не помню.
В общем, если эта проблема мешает нормальной работе твоей программы, то свалить ее ни на что не удастся -- увы, это твоя ошибка.
Тот, кто желает, но не делает, распространяет чуму.