我已经尝试了我能想到的一切,似乎无法使下面的二进制数学逻辑起作用。不知道为什么这会失败,但可能表明我对二进制数学或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。
我很难过。
答案 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);