Jump to content

    

IAR 4.40A

Приветствую, господа!

Есть типа код:

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.

Share this post


Link to post
Share on other sites

Ну а собственно что вас удивляет? Произвольная десятичная дробь в двоичном виде непредставима, отсюда все эти проблемы.

 

x=1.09; // На самом деле результат вычилений 1.[09]
x1=.09; // аналогично, 0.[09]
x-=x1; //[b] это ожидаемо не равно 1[/b]

 

Как вариант - ограничьте точность при выводе - по идее должно помочь ("%.2g" если я правильно помню)

Share this post


Link to post
Share on other sites

"%.14g"? Не помогает.

Здесь идет вычисление погрешности измерений. Нужна точность, которая является никакой, если брать 2 знака.

Edited by IgorKossak
бездумное цитирование

Share this post


Link to post
Share on other sites
Здесь идет вычисление погрешности измерений.

А поподробнее?

Пока что всё выглядит так, будто вы открыли для себя погрешности округления при вычислениях с плавающей точкой. На нобелевку точно не тянет.

Share this post


Link to post
Share on other sites

double x,x1;
x=1092/1001; // Оба числа целые и результаты измерения входного сигнала
x1=1/11; // Константы, указывающие на приращение по отношению измерения 1092
x-=x1; // Исключаем из измерения результат приращения измерения, являющийся погрешностью
sprintf(s,"%.14g",x-1.0); // здесь выводим абсолютную погрешность измерений, которая не должна быть больше 1 (-1)

На каждую строку специально делал вывод значений, всё вычислялось верно. А вот когда делаю -1, то видим -1.11022е-16.

 

Вроде куда уж подробнее...

Share this post


Link to post
Share on other sites
А вот когда делаю -1, то видим -1.11022е-16.

И что? Где проблема? Ожидаемая погрешность, если она отлична от нуля, будет гораздо больше. Следовательно, вот эти малые числа порядка 10^-16 следует считать строго нулём для ваших целей. Короче, ограничивайте точность при выводе результата, как вам и советовали выше.

Share this post


Link to post
Share on other sites
И что? Где проблема? Ожидаемая погрешность, если она отлична от нуля, будет гораздо больше. Следовательно, вот эти малые числа порядка 10^-16 следует считать строго нулём для ваших целей. Короче, ограничивайте точность при выводе результата, как вам и советовали выше.

Чуть выше видно, что она есть. Более того, как объяснить, что с теми же данными по таким же формулам ББ считает верно?

Share this post


Link to post
Share on other sites
Чуть выше видно, что она есть. Более того, как объяснить, что с теми же данными по таким же формулам ББ считает верно?

А кто такой ББ? Борис Борисыч?

Несмотря на то, что есть стандарт IEEE 754 для вычислений с плавающей точкой, там есть ещё разные режимы округления. Не говоря уже о 80-битовом представлении. Поэтому надо ещё разбираться, чем могут отличаться разные среды вычислений.

Share this post


Link to post
Share on other sites
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. Их разность может получиться чуть меньше или чуть больше единицы. У вас получается чуть меньше

 

 

Share this post


Link to post
Share on other sites
Чуть выше видно, что она есть.

Я не увидел.

Вот это "x-=x1; // ожидаемо, 1" - чем вы смотрели? Уверен, что если вывести эту единицу без ограничения точности, там будет 0,999999999999999.

Share this post


Link to post
Share on other sites

ББ - Большой Брат. Комп то есть.

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

Кто же знал про такие особенности...

Share this post


Link to post
Share on other sites
Кто же знал про такие особенности...

Оч. многие знают. Теперь вы тоже :beer:

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this