【问题标题】:Best way to convert an ASCII digit to its numeric value将 ASCII 数字转换为其数值的最佳方法
【发布时间】:2023-03-05 16:35:01
【问题描述】:

假设我有一个代表十进制数字的 ASCII 字符:

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

我想获取它所代表的数值(在09 之间)。 我知道两种可能的方法:

  1. 减法:
    uint8_t value = digit - '0';
    
  2. 按位和:
    uint8_t value = digit & 0x0f;
    

就编译代码大小而言,哪一个最有效? 执行时间处理时间?能源消耗?答案可能是 特定于平台,我最感兴趣的是那种架构 在运行低功耗应用的微控制器中可能会发现: Cortex-M、PIC、AVR、8051等我自己的test on an Arduino Uno 似乎表明在 AVR 上它并没有太大的区别,但是 我仍然想了解其他架构。

额外问题:这两种方法都可以称为“行业标准”吗?是 在哪些情况下选择合适的是必不可少的?

免责声明:这是a discussion 的后续行动 来自 arduino;stackexchange.com 的回答。

【问题讨论】:

  • “哪个效率最高” - 两者都不是。一点都没有关系。在优化的构建中,您很可能会得到相同的程序集。即使您不这样做,像这样的微观优化也只会为您节省纳秒 - 不是您能注意到的任何事情,所以不要担心。
  • digit - '0' 保证适用于所有平台。 digit & 0x0F 适用于我知道的所有平台,但 C 或 C++ 标准不保证数字字符以 BCD 兼容的格式表示所有字符集。
  • @Edgar 我对此表示怀疑。但是,如果您真的需要了解,请运行一些基准测试。
  • @Eljay 问题是关于 ASCII 的。所有其他审议都是题外话
  • Re “行业标准”:我是从另一个用户那里引用的。 @tim:你能详细说明你的意思吗?

标签: c++ c performance embedded energy


【解决方案1】:

你应该自己编译。

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;
}

和代码

__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

【讨论】:

  • 抱歉,我忘了说我想要一个 8 位结果(例如 foo2()foo3())。我刚刚编辑了问题。
  • @EdgarBonet 如您所见,它们是相同的
  • 几乎相同。 subiandi 是不同的指令,涉及 ALU 中的不同门。晶体管开关状态的数量可以不同,因此能耗也不同。一位 stackoverflow 用户告诉我,在低功耗应用程序中,选择正确的应用程序是“必要的”(他的话)。此外,在其他架构上,性能差异可能比在 AVR 上更大。
  • @Edgar 如果您不知道哪个更节能,那么我会质疑花时间找出哪个更高效的必要性。但是,如果两者之间存在实际可衡量的差异,并且已知一种效率更高,那么您为什么不使用它呢?
  • @JohnFilleau 它没有任何区别,因为程序能耗是更广泛的问题,并且程序不仅仅执行这一指令。这是没有任何意义的未成熟优化。
猜你喜欢
  • 2017-12-08
  • 2014-06-21
  • 1970-01-01
  • 2016-08-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-16
  • 1970-01-01
  • 2023-04-08
相关资源
最近更新 更多