Неточное отображение

Обсуждаем контроллеры компании Atmel.
Ответить
Открыл глаза
Сообщения: 79
Зарегистрирован: Ср май 28, 2014 12:55:56

Сообщение zepar »

Доброй ночи! Использую CV AVR, Proteus. Складываю float, результат помещаю в массив char с помощью sprintf и вывожу на LCD через библиотеку командой lcd_puts. Иногда отображаются неточные результаты. Например, 43.9+5 = 48.900001. Или 5/2 = 2, 499998. Притом, если перезапустить выполнение через протеус и проделать тоже самое заново, иногда отображается на ура. Кто тут жульничает и из-за чего?

Добавлено: после пару перезапусков 43.9+5 = 48.899997
Реклама
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 311
Зарегистрирован: Чт фев 10, 2011 10:22:20
Откуда: Беларусь

Сообщение A_AVL »

Так и должно быть. Эти числа нельзя точно представить в двоичном виде. Загуглите "погрешность представления чисел с плавающей точкой"
Контактная информация:
Реклама
Опытный кот
Аватара пользователя
Сообщения: 721
Зарегистрирован: Ср июн 11, 2014 09:43:13
Откуда: США

Сообщение Pink-Pank »

A_AVL писал(а):Эти числа нельзя точно представить в двоичном виде.
Согласен, но у человека одна и та же операция дает разные погрешности. Предположить, что программа, записанная в память контроллера, считает каждый раз по разному - как-то абсурдно.. Думаю, копать нужно в сторону Протеуса.
Fucking static initialization order fiasco
Контактная информация:
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 1900
Зарегистрирован: Сб фев 21, 2009 13:11:40
Откуда: Москва

Сообщение ibiza11 »

согласен. неточность связана именно с ограничениями float, а разные результаты одной и той же операции только эмулятор.
Ставим плюсы: )
Реклама
Эиком - электронные компоненты и радиодетали
Друг Кота
Аватара пользователя
Сообщения: 26876
Зарегистрирован: Пн фев 09, 2009 22:19:49
Откуда: Когда-то был прекрасный город для людей

Сообщение Муркиз »

Обязательно округлять надо с заданной точностью при преобразовании типов чисел для последующих операций.
Реклама
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 335
Зарегистрирован: Вт сен 11, 2007 10:27:08
Откуда: Киев

Сообщение __Alexander »

протеус так лагать не может по определению, это всё выдумки sprintf, который нормальные люди не используют.
Реклама
Опытный кот
Аватара пользователя
Сообщения: 721
Зарегистрирован: Ср июн 11, 2014 09:43:13
Откуда: США

Сообщение Pink-Pank »

И что же там в sprintf записали? генератор случайных чисел? Там заложен какой-то алгоритм, который каждый раз считает одинаково.
Fucking static initialization order fiasco
Контактная информация:
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 311
Зарегистрирован: Чт фев 10, 2011 10:22:20
Откуда: Беларусь

Сообщение A_AVL »

Pink-Pank писал(а):Согласен, но у человека одна и та же операция дает разные погрешности. Думаю, копать нужно в сторону Протеуса.
Погрешность представления float- 1E-7. Все числа у него индицируются в пределах этой погрешности (7 знаков). То что числа преобразуются без округления и разный результат преобразования, зависящий от положения звёзд на небе-это к библиотекам cvavr. IAR, например, своими библиотеками преобразует корректно и с округлением, но и весят эти библиотеки по 8к и жрут под 1к озу.
Контактная информация:
Открыл глаза
Сообщения: 79
Зарегистрирован: Ср май 28, 2014 12:55:56

Сообщение zepar »

__Alexander писал(а):протеус так лагать не может по определению, это всё выдумки sprintf, который нормальные люди не используют.
А чем нынче пользуются нормальные люди ? Как мне отобразить float на LCD ?
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 311
Зарегистрирован: Чт фев 10, 2011 10:22:20
Откуда: Беларусь

Сообщение A_AVL »

В вашем случае - или искать стороннюю нормальную библиотеку sprintf или ftoa, или самостоятельно округлять полученный результат до семи знаков. Больше никак, IMHO.
Контактная информация:
Открыл глаза
Сообщения: 79
Зарегистрирован: Ср май 28, 2014 12:55:56

Сообщение zepar »

A_AVL писал(а):В вашем случае - или искать стороннюю нормальную библиотеку sprintf или ftoa, или самостоятельно округлять полученный результат до семи знаков. Больше никак, IMHO.
Лучше самостоятельно. Но как определить до какого знака именно ? Если брать стабильно 7 знаков, то получается так:
43.999+1 = 44.99899

P.S Я видел когда-то давно, что там сравнивают с числом и еще +- e = 0.00001. Что-то в этом роде. И если, с учетом погрешности e условие верно, то результат округляют.
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 311
Зарегистрирован: Чт фев 10, 2011 10:22:20
Откуда: Беларусь

Сообщение A_AVL »

Ну по идее, 43.999+1 должно быть равно 44.99899?-знак вопроса восьмая цифра, которую вы не привели. так вот, округлять нужно уже преобразованный через sprintf результат до седьмого знака. Вся эта попытка "округлить" float непосредственно у меня ни к чему не привела(и не может ни к чему привести). Использовать нормальные библиотеки от IAR я не стал по причине занимаемой памяти, как и заморачиваться с округлением результата. Но если бы пришлось - то единственный на мой взгляд путь это преобразовать полученную в строке мантиссу из 8 цифр в signed long и затем округлить это число по правилам математики. А потом опять же через sprintf вывести мантиссу отдельно, а порядок отдельно и получить "красивое" число.
Контактная информация:
Открыл глаза
Сообщения: 79
Зарегистрирован: Ср май 28, 2014 12:55:56

Сообщение zepar »

A_AVL писал(а):Ну по идее, 43.999+1 должно быть равно 44.99899?-знак вопроса восьмая цифра, которую вы не привели. так вот, округлять нужно уже преобразованный через sprintf результат до седьмого знака. Вся эта попытка "округлить" float непосредственно у меня ни к чему не привела(и не может ни к чему привести). Использовать нормальные библиотеки от IAR я не стал по причине занимаемой памяти, как и заморачиваться с округлением результата. Но если бы пришлось - то единственный на мой взгляд путь это преобразовать полученную в строке мантиссу из 8 цифр в signed long и затем округлить это число по правилам математики. А потом опять же через sprintf вывести мантиссу отдельно, а порядок отдельно и получить "красивое" число.
Спасибо. Я пришел к выводу, что нужно переводить float в строку самостоятельно без использование sprintf. Можно проконтролировать процесс и отказаться от stdio.h.
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 311
Зарегистрирован: Чт фев 10, 2011 10:22:20
Откуда: Беларусь

Сообщение A_AVL »

Так я ж выам выкладывал библиотеку перевода без использования stdio.h
http://radiokot.ru/forum/viewtopic.php?f=57&t=104581
Останется прикрутить к ней округление мантиссы.
Контактная информация:
Открыл глаза
Сообщения: 79
Зарегистрирован: Ср май 28, 2014 12:55:56

Сообщение zepar »

A_AVL писал(а):Так я ж выам выкладывал библиотеку перевода без использования stdio.h
http://radiokot.ru/forum/viewtopic.php?f=57&t=104581
Останется прикрутить к ней округление мантиссы.
Да, разобрался. Вот еще такой вопрос: в калькуляторе нужно ввести защиту от деления на ноль. Вот такие условия всегда ложные:

Код: Выделить всё

 
1)case '/':  if(x1==0) {lcd_putchar('E'); } else Push(y1/x1); break; 
2)case '/':  if(x1==0.0) {lcd_putchar('E'); } else Push(y1/x1); break; 
3)case '/':  if(x1==0.0f) {lcd_putchar('E'); } else Push(y1/x1); break; 


Можно подумать, дело не в этом? Но такое условие срабатывает:

Код: Выделить всё

  
case '/':  if(x1==5) {lcd_putchar('E'); } else Push(y1/x1); break; 


Ах да, x1 - тип float.
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 311
Зарегистрирован: Чт фев 10, 2011 10:22:20
Откуда: Беларусь

Сообщение A_AVL »

Непонятно. У меня такого не аблюдается. Может с округлением что? Выводится как 0, а на самом деле там не 0?
Контактная информация:
Ответить

Вернуться в «AVR»