Страница 1 из 1

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

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

Добавлено: после пару перезапусков 43.9+5 = 48.899997

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

Добавлено: Пт июн 13, 2014 06:56:49
A_AVL
Так и должно быть. Эти числа нельзя точно представить в двоичном виде. Загуглите "погрешность представления чисел с плавающей точкой"

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

Добавлено: Пт июн 13, 2014 08:21:57
Pink-Pank
A_AVL писал(а):Эти числа нельзя точно представить в двоичном виде.
Согласен, но у человека одна и та же операция дает разные погрешности. Предположить, что программа, записанная в память контроллера, считает каждый раз по разному - как-то абсурдно.. Думаю, копать нужно в сторону Протеуса.

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

Добавлено: Пт июн 13, 2014 08:33:28
ibiza11
согласен. неточность связана именно с ограничениями float, а разные результаты одной и той же операции только эмулятор.

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

Добавлено: Пт июн 13, 2014 09:15:04
Муркиз
Обязательно округлять надо с заданной точностью при преобразовании типов чисел для последующих операций.

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

Добавлено: Пт июн 13, 2014 22:44:35
__Alexander
протеус так лагать не может по определению, это всё выдумки sprintf, который нормальные люди не используют.

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

Добавлено: Сб июн 14, 2014 11:41:22
Pink-Pank
И что же там в sprintf записали? генератор случайных чисел? Там заложен какой-то алгоритм, который каждый раз считает одинаково.

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

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

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

Добавлено: Сб июн 14, 2014 15:56:23
zepar
__Alexander писал(а):протеус так лагать не может по определению, это всё выдумки sprintf, который нормальные люди не используют.
А чем нынче пользуются нормальные люди ? Как мне отобразить float на LCD ?

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

Добавлено: Сб июн 14, 2014 16:30:02
A_AVL
В вашем случае - или искать стороннюю нормальную библиотеку sprintf или ftoa, или самостоятельно округлять полученный результат до семи знаков. Больше никак, IMHO.

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

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

P.S Я видел когда-то давно, что там сравнивают с числом и еще +- e = 0.00001. Что-то в этом роде. И если, с учетом погрешности e условие верно, то результат округляют.

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

Добавлено: Вс июн 15, 2014 22:41:36
A_AVL
Ну по идее, 43.999+1 должно быть равно 44.99899?-знак вопроса восьмая цифра, которую вы не привели. так вот, округлять нужно уже преобразованный через sprintf результат до седьмого знака. Вся эта попытка "округлить" float непосредственно у меня ни к чему не привела(и не может ни к чему привести). Использовать нормальные библиотеки от IAR я не стал по причине занимаемой памяти, как и заморачиваться с округлением результата. Но если бы пришлось - то единственный на мой взгляд путь это преобразовать полученную в строке мантиссу из 8 цифр в signed long и затем округлить это число по правилам математики. А потом опять же через sprintf вывести мантиссу отдельно, а порядок отдельно и получить "красивое" число.

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

Добавлено: Вс июн 15, 2014 23:31:35
zepar
A_AVL писал(а):Ну по идее, 43.999+1 должно быть равно 44.99899?-знак вопроса восьмая цифра, которую вы не привели. так вот, округлять нужно уже преобразованный через sprintf результат до седьмого знака. Вся эта попытка "округлить" float непосредственно у меня ни к чему не привела(и не может ни к чему привести). Использовать нормальные библиотеки от IAR я не стал по причине занимаемой памяти, как и заморачиваться с округлением результата. Но если бы пришлось - то единственный на мой взгляд путь это преобразовать полученную в строке мантиссу из 8 цифр в signed long и затем округлить это число по правилам математики. А потом опять же через sprintf вывести мантиссу отдельно, а порядок отдельно и получить "красивое" число.
Спасибо. Я пришел к выводу, что нужно переводить float в строку самостоятельно без использование sprintf. Можно проконтролировать процесс и отказаться от stdio.h.

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

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

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

Добавлено: Пн июн 16, 2014 19:35:07
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.

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

Добавлено: Вт июн 17, 2014 00:20:42
A_AVL
Непонятно. У меня такого не аблюдается. Может с округлением что? Выводится как 0, а на самом деле там не 0?