[c] тип double

state7401281

должны ли совпадать результаты _арефметических_ (+,-,/,*) вычислений с переменными типа double если используются разные компиляторы? (gcc и msvc)

abrek

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

state7401281

я еще не знаю чем это кончится (не досчиталось)

Vantucha

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

state7401281

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

freezer

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

sergei1969

одна из ошибок у меня на экзамене по Паскалю на 1м курсе - (5.0/2.0) не обязательно 2.5, может быть и 2.4999999999999999
в зависимости от компилятора, платформы...
так что не должны
P.S. и это даже если нет перестановок компилятором

abrek

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

Chupa

>> это не обязательно даже для одного и того же
>> компилятора на одном и том же процессоре.
>
> вот это уже действительно несколько странно ....
совсем даже нет
компилятор может иногда менять порядок выполнения операций
для чисел с плавающей точкой может запросто быть (a+b)+c != a+(b+c
поэтому сходящиея ряды, например, суммируют с конца

state7401281

через ~час скажу результат

Chupa

> как минимум, такая опасная фича должна быть выключена по умолчанию
разумеется
но если юзер явно захочет какой-нибудь -fsuper-puper-fast-math, то сам виноват

abrek

> поэтому сходящиея ряды, например, суммируют с конца
вот ты и объяснил, почему оптимизатор не должен это менять

abrek

а вот интересно, может ли быть 0.5*(a+b)<a , если b>a ?
в своё время в методе деления пополам я писал c = a + 0.5*(b-a) , чтобы защититься от такого

Vantucha

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

sergei1969

пардон, позабыл уже...
не 5.0 / 2.0 , а 5 / 2.0
а критично это было из-за того, что бралось round(a/2.0 соответственно совсем разный результат получаем

abrek

согласен, но никакой -O9 не должен это включать

abrek

двоешник

state7401281

> А зовут его Сергей Яковлевич Ищенко.
это уже хуже .....

Vantucha

стопудово

Chupa

> одна из ошибок у меня на экзамене по Паскалю на 1м курсе - (5.0/2.0) не обязательно 2.5, может быть и 2.4999999999999999
по поводу ....99999...
преобразовать число с плавающей точкой в строку - задача нетривиальная и процесс преобразования может сам вносить некоторую погрешность
в другую сторону тоже самое, хотя 5, 5.0 и 2.0 слишком хорошие числа, чтобы это к ним относилось
у FPU есть несколько режимов округления, но там нет "нормального", который сделает 3 из 2.5 и 2 из 2.4(9)
там есть отбрасывание разрядов (ближайшее целое в сторону нуля округление вверх или вниз,
а также округление к ближайшему целому или чётному, т.е. из 2.5 и 1.5 он сделает 2

freezer

такая опасная фича должна быть выключена по умолчанию

гы-гы! В VC++ 7.1 все как раз наоборот
/Op disables optimizations that could change the precision of floating-point numbers

или я что-то путаю?

state7401281

результат совпадает
могут ли не совпадают такие штуки: a - b и a + - b?

Ivan8209

Нет, если нет приведения типов.
---
...Я работаю антинаучным аферистом...

Ivan8209

А там получается 2,4(9)?
А вдруг там 2,4(9)8?
---
...Я работаю антинаучным аферистом...

freezer

кстати да:


double a;
unsigned b;

Chupa

из контекста должно быть понятно, что именно там обозначено символом "2.4(9)", поэтому твоё замечание не в кассу

Ivan8209

b a - ( Здесь может быть потеря значимости или переполнение )
-1 scaled ( Здесь только потеря значимости )
( или 2 / --- один чёрт )
a + ( здесь --- переполнение )
против
a b +
-1 scaled
В первом случае должна быть пол. беск., если вдруг числа очень далеки,
во втором --- любая беск., если числа очень близки.
Далее что может быть нехорошего.
Если b большое, а а маленькое, то:
1) b-a = b и может быть округлено вниз;
2) a+b = b ... .
Если наоборот...
Лень полностью расписывать.
Я не вижу причин, чтобы порядок отличался от ожидаемого.
Единственное, это неравенство становится нестрогим.
a<= (a+b)/2 <= b.
---
...Я работаю антинаучным аферистом...

Ivan8209

Я сейчас не скажу, как ведёт себя сопроцессор при округлении двоичного +1,1 и иже с ними, при "к ближайшему."
Но команда сравнения с нулём есть и округлить как надо никто не может помешать.
---
...Я работаю антинаучным аферистом...
Оставить комментарий
Имя или ник:
Комментарий: