Так что я сделал эту функцию на микроконтроллере 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?
Это из-за преобразования типов.
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;
digit
объявлен как unsigned short
поэтому любое назначенное ему десятичное значение будет усечено. Деление, которое вы делаете, дает float
значение, которое вы пытаетесь сохранить в digit
, поэтому он будет усечен для хранения в виде unsigned short
,
Возможно, вы захотите изменить тип digit
к float
если вы можете сэкономить место.