简体   繁体   中英

C++ - Type conversion error

So I've made this function on an AVR microcontroller that works OKish, but when I call

display(1)

the value shown on the 4 digit display is "1.099" instead of "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;
}

The "n" variable, which is supposed to be shown, is a float, so why is the precision lost starting with the second decimal during

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

Is it because of type conversion? Is it because of some 8bit RISC processor limitation?

It's because of type conversion.

float is not precise, so when you do 1/.01 and 1/.001 in floating point, you get slightly less than 100 and 1000. (I didn't want to trace your code all that thoroughly, but that is where the problem lies.) This is rounded down to 99 and 999, which is why the 9s show up in the output.

You would be much better off to work in integers, if you can. Prevent rounding down by adding half the value of the last expected digit.

It seems like you are expecting values between 0.001 and 9999. A quick implementation would use cases:

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

Another tip, you don't need to use the % operator. Compute the digits from the right and store them before displaying.

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

digit is declared as an unsigned short , so any decimal value assigned to it will be truncated. The division you are doing yields a float value which you are trying to store in digit , so it will be truncated to be stored as an unsigned short .

You will probably want to change the type of digit to a float if you can spare the space.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM