添加00000001时,为什么这个二进制数学会失败,否则会正常工作?

时间:2017-11-11 20:38:22

标签: math arduino binary addition

我已经尝试了我能想到的一切,似乎无法使下面的二进制数学逻辑起作用。不知道为什么这会失败,但可能表明我对二进制数学或C的误解。最终意图是将大整数(无符号长整数)直接存储到8位FRAM存储器模块中作为4字节字,以便微控制器( Arduino)可以在电源故障后恢复值。因此,无符号长整数必须从它的4字节字部分组装,因为它从存储器中拉出,并且组装这些字字节的算法不能正常工作。

在下面的代码片段中,long值定义为四个字节A,B,C和D(模拟从四个8位内存块中拉出),它们被转换为十进制表示法,用作在DDDDDDDDCCCCCCCCBBBBBBBBAAAAAAAA安排中无符号长。如果A< 256和B,C,D all == 0,数学运算正常。如果A == 0,数学也适用于B,C和D的任何值。如果B,C或D> 0和A == 1,算术期间不添加A的1值。值为2有效,但值不是1.这有什么理由吗?还是我做二进制数学错了?这是一个需要解决方法的已知问题吗?

// ---- FUNCTIONS

unsigned long fourByte_word_toDecimal(uint8_t byte0 = B00000000, uint8_t byte1 = B00000000, uint8_t byte2 = B00000000, uint8_t byte3 = B00000000){
  return (byte0 + (byte1 * 256) + (byte2 * pow(256, 2)) + (byte3 * pow(256, 3)));
}

// ---- MAIN
void setup() {

  Serial.begin(9600);

  uint8_t addressAval = B00000001;
  uint8_t addressBval = B00000001;
  uint8_t addressCval = B00000001;
  uint8_t addressDval = B00000001;

  uint8_t addressValArray[4];
  addressValArray[0] = addressAval;
  addressValArray[1] = addressBval;
  addressValArray[2] = addressCval;
  addressValArray[3] = addressDval;

  unsigned long decimalVal = fourByte_word_toDecimal(addressValArray[0], addressValArray[1], addressValArray[2], addressValArray[3]);

  // Print out resulting decimal value
  Serial.println(decimalVal);

}

在上面的代码中,二进制值应为00000001000000010000000100000001,AKA为十进制值16843009. 但代码将十进制值计算为16843008. 将addressAval的值更改为00000000也会计算(正确)到16843008,并将addressAval更改为00000010也正确评估为16843010。

我很难过。

2 个答案:

答案 0 :(得分:0)

问题是您正在使用pow()。这导致一切都被计算为二进制32,它没有足够的精度来保存16843009。

>>> numpy.float32(16843009)
16843008.0

修复是使用整数,特别是65536和16777216UL。

答案 1 :(得分:0)

请勿使用pow()

通常的方法是使用移位运算符:

uint32_t result = uint32_t(byte3 << 24 | byte2 << 16 | byte1 << 8 | byte0);