【问题标题】:A Bit Shift-like function or algorithm that returns four bytes output of numbers input [closed]返回数字输入的四个字节输出的类似位移位的函数或算法[关闭]
【发布时间】:2016-03-01 16:04:14
【问题描述】:

您好,我正在尝试开发一个 C++ 函数或算法,其行为类似于位移该函数将始终返回从 099999999 范围内的任何数字输入的 4 字节 00 00 00 00

输入 (int) -> 预期输出(字符或字符串)

0 -> 00 00 00 00
20 -> 00 00 20 00
200 -> 00 02 00 00
2000 -> 00 20 00 00
99999999-> 99 99 99 99

并且可以反转以返回原始数字。

输入(字符或字符串)-> 预期输出(int/double)

00 00 20 00 -> 20
00 02 00 00 -> 200
00 20 00 00 -> 2000
99 99 99 99 -> 99999999

编辑

这是我的代码。它接近于我正在寻找的东西,但仍在进行中:

void Convert_to_Decimal(std::string str)
{
    double ret;
    ///insert . after string number 6.
    str.insert(5,1,'.');
    str.erase(0, str.find_first_not_of('0'));
    ///remove leading zeros
    ret =std::stod(str.c_str());
    printf("%g\n", ret);
}

Convert_to_Decimal("00020000");

我将不胜感激任何解决此问题的指针或解决方案,在此先感谢您

【问题讨论】:

  • 你能把你写的代码贴出来吗?好像不太难,先用strtol把字符串转成整数,然后解析小数部分完成整数,最后把整数转成BCD输出字节。
  • 00 00 00 00 4 位怎么样?如果它可以包含 8 个十进制数字,那么它肯定是超过 4 位的信息。另外,如何将整数转换为不同格式的字符串位移?
  • @kelvinWells 我不知道该怎么称呼它,这就是为什么我说它类似于位移,更重要的是它的 4 字节数据用于串行端口命令@chqelie 20 的 bcd 格式是 @ 987654331@它没有达到我想要实现的目标
  • 看起来它只是带有隐式小数点的 BCD。您在编写此转换的代码时遇到了什么问题?
  • 看起来你之前的大部分问题都是关于这个问题的?一些一般性建议:您可能需要退后一步,确保您首先了解底层算法 - 尝试为您不完全理解的东西编写代码是一种随意的方法 - 看看你是否可以用铅笔和纸来做首先,然后才尝试编写代码。

标签: c++ c algorithm


【解决方案1】:

这是一个简单的解决方案:

#include <stdint.h>

/* encode a number given as a string into a 4 byte buffer */
void number_convert(unsigned char *dest, const char *str) {
    uint32_t v = 0;
    while (*str >= '0' && *str <= '9') {
        /* parse digits and encode as BCD */
        v = (v << 4) + (*str++ - '0');
    }
    /* make room for 2 decimal places */
    v <<= 8;
    if (*str == '.') {
        if (str[1] >= '0' && str[1] <= '9') {
            /* set number of tenths */
            v += (str[1] - '0') << 4;
            if (str[2] >= '0' && str[2] <= '9') {
                /* set number of hundredths */
                v += (str[2] - '0');
            }
        }
    }
    /* store the BCD value in big endian order */
    dest[0] = (v >> 24) & 255;
    dest[1] = (v >> 16) & 255;
    dest[2] = (v >>  8) & 255;
    dest[3] = (v >>  0) & 255;
}

void test(const char *str) {
    unsigned char buf[4];

    number_convert(buf, str);
    printf("%s -> %02X %02X %02X %02X\n", str, buf[0], buf[1], buf[2], buf[3]);
}

int main(void) {
    test("0");
    test("20");
    test("200");
    test("2000");
    test("123.1");
    test("999999.99");
    return 0;
}

编辑

您的代码使用float 变量。你的问题不清楚:你想计算 4 个字节吗?为此,您应该使用字节数组,否则,请为您尝试实现的聊天提供更准确的解释。

要将 4 字节数字数组转换回数字,您可以这样做:

double convert_BCD_to_double(unsigned char *str) {
    long res = 0;
    for (int i = 0; i < 4; i++) {
        res = res * 100 + (str[i] >> 4) * 10 + (str[i] & 15);
    }
    return (double)res / 100;
}

【讨论】:

  • @MelFzlic:这个答案符合你的需要吗?
  • 我在短途旅行中离开,我试图修改你的函数,但试图计算你的代码返回值是 int 没有返回符号,所以我将其更改为 void但仍然无法解决问题,你能提供给我用例吗?谢谢
  • @MelFzllc:关于返回类型的要点。我添加了一些测试代码。你的意思是让99999999 产生99 99 99 99 吗? 999999.99 不应该产生那个吗?
  • 上面的代码回答了你原来的问题。您对其进行了编辑以删除小数点处理,您是否还应该更改示例,例如200 -&gt; 00 00 02 00等。
  • 谢谢,您的功能确实有效,也感谢您的耐心等待,我正在与一位必须更新值的队友一起工作。我一定会开始反转这个过程,用你的指针得到十进制数
【解决方案2】:

对于整数,让我们将移位定义为将数字乘以或除以其表示基数。
对于十进制,右移:
300 --&gt; 30
十六进制:
0x345 --&gt; 0x34
二进制:
1101 --&gt; 110

对于十进制,右移一位需要除以 10。对于十六进制,除以 16,对于二进制,除以 2。

左移是乘以基数:十进制 - 乘以 10,十六进制乘以 16,二进制乘以 2。

当移位超出数字的边缘时,您无法通过向另一个方向移位来恢复原始数字。

例如,将 345 右移一位产生 34。没有办法通过左移一位来将 5 恢复。常见的规则是当一个数字移位时,引入一个新的数字 0。因此 34 左移一位得到 340。

关于你的浮点数。我看不出字节 99 99 99 99 如何产生 999999.99。最后一个字节总是在小数点右边吗?

对于移位字节,使用运算符 >。您希望使用包含字节数量的最大大小整数,例如 uint32_t 用于 4 字节值。另外,请使用unsigned 数字,因为您不希望 signed 表示干扰移位。

编辑 1:示例函数

uint32_t Shift_Left(unsigned int value, unsigned int quantity)
{
  while (quantity > 0)
  {
    value = value * 2;
  }
  return value;
}

uint32_t Shift_Left(unsigned value, unsigned int quantity)
{
  return value << quantity;
}

对于按字节移位,将数量设置为 8 或 8 的倍数(每字节 8 位)。

【讨论】:

    猜你喜欢
    • 2017-08-01
    • 1970-01-01
    • 2012-08-05
    • 2019-07-16
    • 2011-08-30
    • 2018-02-13
    • 2014-08-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多