Ошибка преобразования типа

Так что я сделал эту функцию на микроконтроллере AVR, который работает OKish, но когда я звоню

display(1)

значение, отображаемое на 4-значном дисплее, равно «1.099» вместо «1.000».

void display(float n) {
int8_t i, digit_pos=0;
unsigned short digit;
PORTC &= ~((1<<MUX_A2) | (1<<MUX_B2) | (1<<MUX_E2));
ENABLE_DISPLAY;

for (i=3;i>=-3;i--)
{
digit = n/pow(10,i);
digit = digit%10;
if (digit==0&&i>0&&digit_pos==0)
continue;
if (digit_pos-i<3)
if (i==0)
digit += 10;

PORTD = SegCode[digit];
PORTC = ((PORTC & (~(3<<MUX_A2))) | (digit_pos<<MUX_A2)) & ~(1<<MUX_E2);
PORTC |= (1<<MUX_E2);
if (digit_pos==3)
break;
else
digit_pos++;
}

PORTD=0x00;
}

Переменная «n», которая должна быть показана, является плавающей точкой, так почему точность теряется, начиная со второго десятичного знака во время

digit = n/pow(10,i);
digit = digit%10;

Это из-за преобразования типов? Это из-за ограничений на 8-битный процессор RISC?

0

Решение

Это из-за преобразования типов.

float не является точным, поэтому, когда вы делаете 1 / .01 и 1 / .001 в плавающей точке, вы получаете чуть меньше 100 и 1000. (Я не хотел тщательно отслеживать ваш код, но именно в этом проблема ложь.) Это округляется до 99 и 999, поэтому 9 выводятся на выходе.

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

Похоже, вы ожидаете значения от 0,001 до 9999. Быстрая реализация будет использовать случаи:

if (n > 9999) error
else if (n >= 1000) {dec = (int)(n + 0.5); shift = 0;}
else if (n >= 100) {dec = (int)(10*(n + 0.05)); shift = 1;}
and so on

then do stuff with dec

Еще один совет, вам не нужно использовать оператор%. Вычислите цифры справа и сохраните их перед отображением.

dec_next = dec / 10;
digit = dec - 10*dec_next;
dec = dec_next;
2

Другие решения

digit объявлен как unsigned shortпоэтому любое назначенное ему десятичное значение будет усечено. Деление, которое вы делаете, дает float значение, которое вы пытаетесь сохранить в digit, поэтому он будет усечен для хранения в виде unsigned short,

Возможно, вы захотите изменить тип digit к float если вы можете сэкономить место.

1