Перейти к содержанию
    

Занимательная арифметика с CCS

CCS 4.1.3. В комментариях результат присвоения. Как такое может быть?

 

int a1 = (int)(60.0/1.2); // = 49

int a2 = (int)(60.0/1.2 + 0.5); // = 50

Изменено пользователем Абырвалг

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

CCS 4.1.3. В комментариях результат присвоения. Как такое может быть?

 

int a1 = (int)(60.0/1.2); // = 49

int a2 = (int)(60.0/1.2 + 0.5); // = 50

 

ошибка представления

округляет так, что

(60.0/1.2) = 49.999999

очевидно (int)(60.0/1.2 + 0.5) = 50

да и (int)(60.0/1.2 + 0.001) = 50

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Это то понятно. Но это же ненормально? Раньше с таким не сталкивался, неужто такое в норме вещей?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Это то понятно. Но это же ненормально? Раньше с таким не сталкивался, неужто такое в норме вещей?

 

Бывает. Ошибки округления при вводе числа. Типа 1.2 = 1.200001 примерно

Как-то обсуждали, правда для библиотеки программной укороченых float16-float32 blackfin,

а здесь намудрили прямо в компиляторе

Не страшно, хоть и неожиданно.

Если не использовать int а использовать правильное округление floor(x+0.5), то результат будет всегда ожидаемый

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Бывает. Ошибки округления при вводе числа. Типа 1.2 = 1.200001 примерно

Как-то обсуждали, правда для библиотеки программной укороченых float16-float32 blackfin,

а здесь намудрили прямо в компиляторе

Не страшно, хоть и неожиданно.

Если не использовать int а использовать правильное округление floor(x+0.5), то результат будет всегда ожидаемый

 

Использовать вызов функции для вычисления константы, да еще такой простой? На это я пойтить не могу.

 

И чем приведение к целому типу хуже? И там +0.5 надо добавить, и тут.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

И чем приведение к целому типу хуже? И там +0.5 надо добавить, и тут.
Надо всегда помнить, что флор() - плавающий целый. Пред. автор этого не помнит. 1.2 = 1 + 1/5. Одну пятую в двоичном виде не представить в виде конечной дроби, 1.2 -> 1.999.... или 0x3F99999A с округлением. Иначе никак. Соответственно, преобразование в целое будет, как и сосчитал компилятор или процессор - правильно округлив в целое. И, вообще, а + в = а или а + в = в...

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Надо всегда помнить, что флор() - плавающий целый. Пред. автор этого не помнит. 1.2 = 1 + 1/5. Одну пятую в двоичном виде не представить в виде конечной дроби, 1.2 -> 1.999.... или 0x3F99999A с округлением. Иначе никак. Соответственно, преобразование в целое будет, как и сосчитал компилятор или процессор - правильно округлив в целое. И, вообще, а + в = а или а + в = в...

 

Флор округляет вниз, 1.2 -> 1. Но 1.2 в целое преобразовывать мне не надо. 60/1.2 надо.

 

Конкретно в этом примере 60 - сисклок в МГц, 1.2 МГц - частота PWM для вывода наружу. 60/1.2 = 50. При обнулении таймера в него загружается 50-1=49. Чтобы не вспоминать после что такое 49, при инициализации таймера в регистр периода записывается (int) (60/1.2-1). Если результат в скобках целый, то и проблем, как мне казалось, быть не должно. Всю жисть так делал и горя не знал. Вроде и в CCS2 такое использовал, хотя божиться не буду а проверять не охота.

 

Если надо округлить нецелую константу, то добавлял +0.5 и то же отбрасывание дробной части через приведение типа: (int) (60/1.2-1+0.5). Такое и с этими приколами ccs4 работать будет. Вообще понятно почему так происходит, но просто не ожидал такого подвоха. В любом калькуляторе при вычислении 60/1.2 вы получите 50, а не 49.(9). В калькуляторах вроде есть лишний разряд, который вычисляется но не отображается, а используется для округления результата.

 

В чем преимущество флор() - не понял. Вроде никакого, кроме лишнего кода.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

а может 600/12 ?

или типа в килогерцах 60000/1200 и камент в исходнике, мол так и так...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

или типа в килогерцах 60000/1200 и камент в исходнике, мол так и так...

 

Ага, вариант.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

double i = 0.0 ;

do {

i = i + 0.1 ;

} while( i != 1.0 );

 

 

Затем заменить 0.1 на 0.125.

 

Просветляет относительно представления вещественных чисел.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Предлагаю всем набросать циклу [...]

Просветляет относительно представления вещественных чисел.

В основном, неубедительно. Этот цикл (и сотни и тысячи ему подобных) иллюстрирует следствие, но не анализирует причину.

 

Причины обоснованы в David Goldberg, What Every Computer Scientist Should Know About Floating-Point Arithmetic, ACM Computing Surveys, Vol 23, No 1, March 1991. Этой же и сходными проблемами в разное время занималось много математиков, от П.Л.Чебышева до У.Кахана (вместо до нужно вписать много известных имён)...

 

Оригинальная статья из ACM CS и из NCG @ http://docs.sun.com/ :

Goldberg_1991.pdf

goldberg.pdf

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

вычислителей всегда учат учитывать эту ошибку. особенно при переводе к целому.

всегда стоял вопрос куда округлять и граница=)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...