LINUX.ORG.RU

C, операции с числами с плавающей точкой


0

0

Приветствую. Столкнулся с невполне понятной ситуацией - изменение точности рассчетов с числами с плавающей точкой. Простейший пример:

$ cat test.c

#include <stdio.h>

int main()
{
	double x = 1.23523999932567346;
	
	double y;
	unsigned int i;
	for (i = 1; i < 100000; i *= 10)
	{
		y = x*i;
		printf("%.32f * %d = %.32f\n", x, i, y);
	}

	return 0;
}

Результат исполнения:

$ ./a.out |column -t

1.23523999932567352111334457731573  *  1      =  1.23523999932567352111334457731573
1.23523999932567352111334457731573  *  10     =  12.35239999325673565522265562321991
1.23523999932567352111334457731573  *  100    =  123.52399993256734944679919863119721
1.23523999932567352111334457731573  *  1000   =  1235.23999932567357973312027752399445
1.23523999932567352111334457731573  *  10000  =  12352.39999325673488783650100231170654

С 17 символа результата умножения идут существенные различия. Т.е. результат умножения отличен от того, что бы получил я, сделав это руками.

С чем это связано(с принципом хранения чисел с п.т. или ...)? Как этого избежать(long double также не спасает). Что почитать? Спасибо

> с принципом хранения чисел

Да.

Как этого избежать


Думать головой, когда формулируешь выражения.

Что почитать?


1. Учебник арифметики, раздел про приближенные вычисления.

2. Как ни смешно, из русской литры этот вопрос хорошо освещен у Монахова «Явабинс: программирования на яве» или как-то так. Более фундаментально - у Петцольда «Код: чего-то там».

LamerOk ★★★★★
()

Конкретно в вашем случае можно использовать не числа с плавающей точкой, а рациональные числа (т.е. хранить 2 целых числа). В этом случае операции, не выводящие из множества рациональных чисел, будут точные.

Legioner ★★★★★
()

> С чем это связано(с принципом хранения чисел с п.т. или ...)?

http://en.wikipedia.org/wiki/IEEE_754-1985
http://en.wikipedia.org/wiki/IEEE_754-2008

Как этого избежать(long double также не спасает). Что почитать? Спасибо


Использовать bignum (например, писать на Common Lisp, где оно из коробки ;). В Си такого нет, придётся мучаться с gmp.

mv ★★★★★
()
Ответ на: комментарий от kto_tama

вы еще питон посоветуйте :-)

Если автор пишет какую-нибудь несложную рассчётку, то почему бы и нет?

mv ★★★★★
()

>Как этого избежать(long double также не спасает).

Лучше сначала задумайся, зачем тебе такая точность.

Если ты не в курсе про машинное представление чисел, но при это тебе нужна такая точность, значит ты скорее всего как-то не так решаешь поставленную задачу.

anonymous
()

Хороших советов надавали, правильных. Жаль, что тролль не оценит.

annoynimous ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.