Edgar Bonet
Edgar Bonet

Reputation: 3566

Best way to convert an ASCII digit to its numeric value

Lets say I have an ASCII character representing a decimal digit:

char digit;  // between 0x30 ('0') and 0x39 ('9') inclusive

I want to get the numeric value it represents (between 0 and 9). I am aware of two possible methods:

  1. subtraction:
    uint8_t value = digit - '0';
    
  2. bitwise and:
    uint8_t value = digit & 0x0f;
    

Which one is the most efficient in terms of compiled code size? Execution time? Energy consumption? As the answer may be platform-specific, I am most interested about the kind of architectures one may find in microcontrollers running low-power applications: Cortex-M, PIC, AVR, 8051, etc. My own test on an Arduino Uno seems to indicate that on AVR it doesn't make much of a difference, but I still would like to hear about other architectures.

Bonus questions: can either method be called “industry standard”? Are there situations where choosing the right one is essential?

Disclaimer: this is a followup to a discussion on an answer from arduino;stackexchange.com.

Upvotes: 0

Views: 374

Answers (1)

0___________
0___________

Reputation: 67546

You should compile it yourself.

int foo(char x)
{
    return x - '0';
}

int foo1(char x)
{
    return x & 0x0f;
}

char foo2(char x)
{
    return x - '0';
}

char foo3(char x)
{
    return x & 0x0f;
}

and the code

__tmp_reg__ = 0
foo(char):
        mov __tmp_reg__,r24
        lsl r0
        sbc r25,r25
        sbiw r24,48
        ret
foo1(char):
        andi r24,lo8(15)
        ldi r25,0
        ret
foo2(char):
        subi r24,lo8(-(-48))
        ret
foo3(char):
        andi r24,lo8(15)
        ret

Upvotes: 1

Related Questions