|
|
  |
IAR 4.40A, Ошибка в вычислении с плвающей зпт |
|
|
|
Oct 27 2016, 10:09
|
Участник

Группа: Участник
Сообщений: 63
Регистрация: 21-09-07
Из: СССР
Пользователь №: 30 719

|
Приветствую, господа! Есть типа код: CODE double x,x1; x=1.09; // На самом деле результат вычилений 1.[09] x1=.09; // аналогично, 0.[09] x-=x1; // ожидаемо, 1 sprintf(s,"%g",x-1.0); // Вот и проблема! -1.11022е-16 У кого есть идеи, как побороть? Пробовал в другом компилере, результат, ессно, 0. Более того, эти же данные (в сыром виде) передаются на комп, там по той же формуле из тех же данных идет вычисление, и получается 0. Компилер менять не тема - много переносить, и слишком много использовано особенностей данной версии. Исходные данные: IAR 4.40A (4.42A), AT91SAM7X256 (ARM7), CPP.
--------------------
Сомневаюсь, и вам советую!
|
|
|
|
|
Oct 27 2016, 10:17
|
Знающий
   
Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153

|
Ну а собственно что вас удивляет? Произвольная десятичная дробь в двоичном виде непредставима, отсюда все эти проблемы. Код x=1.09; // На самом деле результат вычилений 1.[09] x1=.09; // аналогично, 0.[09] x-=x1; //[b] это ожидаемо не равно 1[/b] Как вариант - ограничьте точность при выводе - по идее должно помочь ("%.2g" если я правильно помню)
|
|
|
|
|
Oct 27 2016, 10:25
|
Участник

Группа: Участник
Сообщений: 63
Регистрация: 21-09-07
Из: СССР
Пользователь №: 30 719

|
"%.14g"? Не помогает. Здесь идет вычисление погрешности измерений. Нужна точность, которая является никакой, если брать 2 знака.
Сообщение отредактировал IgorKossak - Oct 27 2016, 19:09
Причина редактирования: бездумное цитирование
--------------------
Сомневаюсь, и вам советую!
|
|
|
|
|
Oct 27 2016, 10:38
|
Участник

Группа: Участник
Сообщений: 63
Регистрация: 21-09-07
Из: СССР
Пользователь №: 30 719

|
Код double x,x1; x=1092/1001; // Оба числа целые и результаты измерения входного сигнала x1=1/11; // Константы, указывающие на приращение по отношению измерения 1092 x-=x1; // Исключаем из измерения результат приращения измерения, являющийся погрешностью sprintf(s,"%.14g",x-1.0); // здесь выводим абсолютную погрешность измерений, которая не должна быть больше 1 (-1) На каждую строку специально делал вывод значений, всё вычислялось верно. А вот когда делаю -1, то видим -1.11022е-16. Вроде куда уж подробнее...
--------------------
Сомневаюсь, и вам советую!
|
|
|
|
|
Oct 27 2016, 10:50
|
Участник

Группа: Участник
Сообщений: 63
Регистрация: 21-09-07
Из: СССР
Пользователь №: 30 719

|
Цитата(scifi @ Oct 27 2016, 13:46)  И что? Где проблема? Ожидаемая погрешность, если она отлична от нуля, будет гораздо больше. Следовательно, вот эти малые числа порядка 10^-16 следует считать строго нулём для ваших целей. Короче, ограничивайте точность при выводе результата, как вам и советовали выше. Чуть выше видно, что она есть. Более того, как объяснить, что с теми же данными по таким же формулам ББ считает верно?
--------------------
Сомневаюсь, и вам советую!
|
|
|
|
|
Oct 27 2016, 10:59
|
Знающий
   
Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153

|
Цитата(mungo @ Oct 27 2016, 13:38)  Код double x,x1; x=1092/1001; // Оба числа целые и результаты измерения входного сигнала x1=1/11; // Константы, указывающие на приращение по отношению измерения 1092 x-=x1; // Исключаем из измерения результат приращения измерения, являющийся погрешностью sprintf(s,"%.14g",x-1.0); // здесь выводим абсолютную погрешность измерений, которая не должна быть больше 1 (-1) Вы почитайте все ж что такое числа с плавающей точкой в двоичном представлении. У вас есть примерное представление 1092/1001 и такое же примерное представление 1/11. Более того, точность представления 1/11 больше, чем точность представления 1092/1001. Их разность может получиться чуть меньше или чуть больше единицы. У вас получается чуть меньше
|
|
|
|
|
Oct 27 2016, 11:07
|
Участник

Группа: Участник
Сообщений: 63
Регистрация: 21-09-07
Из: СССР
Пользователь №: 30 719

|
ББ - Большой Брат. Комп то есть. Ок, я был не прав, дьявол кроется в деталях. Похоже, что хардварный калькулятор в ББ работает иначе, как впрочем и софтварный в IAR 7.5. То есть для данной точности в 4.40 он то, что считает слишком малым числом, оставляет хвостом, а остальные его отбрасывают. Поэтому получаем не ровно 1, а 1.[куча нолей]9. Вот оттуда и минус... Кто же знал про такие особенности...
--------------------
Сомневаюсь, и вам советую!
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|