Re[8]: Информация для размышления
От: XXXL  
Дата: 22.10.03 12:54
Оценка:
Всем привет!
Для меня тоже оказалась актуальна тема округления.
У меня для вас есть немного вкусненького.
Есть небольшая модификация алгоритма округления до любого
числа знаков после запятой:

double round( double val, unsigned signs ) //[1]
{
double p = pow( 10., signs );
return floor( val * p + .5 ) / p;
}

val — само число,
signs — количество знаков после запятой.

...

Например,

round( 1.15, 1 ) == 1.2;
round( 1.555, 2 ) == 1.56;

Но,

round( 0.285, 2 ) == 0.28; //!!!!!!!!!

Когда должно получиться 0.29!

Исследуя, природу этой ошибки, меня посетила такая мысль.
Что не любое число может быть представлено в формате типа
double. Одним из этих чисел является 0.285, и то что мы
видим 0.285 — это не так. На самом деле число 0.285
представлено числом, близким к нему, это число
0.284(9) ( 9 в периоде ). В доказательство этому привожу
фрагмент кода:

1. double integer;
2. double fractional;
3. fractional = modf( 0.285 * 100., &integer );
4. int iv = (int)( fractional * 100. );

После выполнения строки номер 4 переменная iv принимает значение,
как вы думаете, не 50, а 49!

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

Примечание: В компиляторе Borland Pascal 7.0 округление,
вроде корректно со всеми числами. Может все дело в структуре
хранения чисел с плавающей запятой в C?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.