В каких ситуациях вещественной машинной арифметики не выполняются законы ассоциативности и дистрибутивности в C, C++?
Есть законы ассоциативности: (х + у) + z = x + (y + z) и (x * y) * z = x * (y * z). Также есть закон дистрибутивности: (х + у) * z = x * z + y * z. В вещественной машинной арифметике данные законы выполняются не во всех случаях. В каких именно случаях это происходит? Если это связано со значениями переменных, то при каких значениях законы не будут выполняться? Желательно с примерами на языке.
Ответы (1 шт):
Математические законы выполняются всегда. А вот указанные вами равенства могут не выполняться, только это не имеет никакого отношения к математическим законам - здесь имеет значение формат хранения чисел в памяти машины. Также это относится не только к арифметике вещественных чисел.
Так, при любых операциях может быть переполнение числа. Например, если у вас тип данных беззнаковый 8-битный unsigned char то максимальное число которое в нем можно хранить - 255. И тогда равенство (250 + 7) - 3 = 250 + (7 - 3) не выполнится, т.к. в левой части произойдет переполнение а в правой - нет.
При операциях с вещественными числами компьютерный формат хранения не позволяет выразить любое число - числа хранятся с округлением. Так, к примеру число 0,2 в вещественной переменной float будет хранится как 0,200000003. Или прибавление маленьких чисел к большим числам не меняет результат - например 1e22 + 1 == 1e22. Ну или как написал AlexGlebe 1e9 + 1e-9 == 1e9. Потому что прибавляемое число меньше погрешности, с которой хранится первое число. Из-за этого могут как-бы "не выполняться" свойства операций - ассоциативности и дистрибутивности. Например (1e22 - 1e22) + 1 == 1 a 1e22 - (1e22 - 1) == 0.
Обо всем этом рассказывается в книгах и курсах по "Data Science" (на русском - наука о данных), также в интернете. Например статья