Тема: Дробові числа. Частина 2
Як і обіцяв в першій статті, в цій я напишу про деякі проблеми такого представлення чисел.
Перша і напевно найбільш очевидна проблема: існує певна похибка при збережені чисел, при чому чим дальше від 0 число тим більша похибка. Це можна перевірити на такому прикладі:
З математичної точки зору результат мав би бути 90.0, але насправді буде виведено 64.0.
Все тому, що 999999999d = 4e6e6b28h(ieee) = 1000000000d, тобто похибка склала +1.
А 999999909d = 4e6e6b27h(ieee) = 999999936d, а тут +27.
Другою проблемою є помилки при приведені типів. Для прикладу:
Знов ж таки, з математичного боку мало б вивести 0.0 але насправді виводить -2.876544. Загалом причина цього майже така ж як і попередня. Число в типі double, було збережено більш точно ніж в типі float через що вийшов такий результат.
Щоб цього уникнути треба перед такими діями приводити числа до одного типу, а якщо конкретніше до до того типу який має меншу розрядність. Тобто останню стрічку цього прикладу треба замінити на
printf("%f\n", (float)a-b);
Для цієї проблеми можна навести ще один приклад
І знову мало б вивести 0, але виводить 0.333333. Це відбувається тому що вираз 1/3 обчислюється з більшою точністю а саме в типі double. Щоб цього уникнути треба явно привести числа 1 і 3 до типу float, або зберігати змінні a, b, c в типі double.
Наступна проблема в неправильності виконання операцій з дуже різними числами, тобто тими в яких не перетинаються експоненти. Приклад:
Ще раз мало б вивести 0 але виводить 8.299232. Тут просто треба робити компенсацію:
Хоча невелика похибка залишилась( а саме 0.000003 ) .
P.S. Вибачайте за не надто інформативні назви змінних просто було лінь вигадувати назви.