Arduino中String与char数组转long结果不一致问题及修正需求
32位二进制字符串转long的问题与修复
volatile long pakiet = 0; String longToBinaryString(long num) { String result = ""; for (int i = 31; i >= 0; i--) { if ((num >> i) & 1) { result += "1"; } else { result += "0"; } } return result; } bool isNumber(String str) { for (int i = 0; i < str.length(); i++) { if (!isdigit(str.charAt(i))) { return false; } } return true; } long readBinaryString(char *s) { long result = 0; while (*s) { result <<= 1; if (*s++ == '1') result |= 1; } return result; } long binaryToLong(String binaryString) { long result = 0; for (int i = 0; i < binaryString.length(); i++) { if (binaryString.charAt(i) == '1') { result += pow(2, binaryString.length() - i - 1); } } return result; } void setup() { Serial.begin(115200); Serial.println("yo"); } void loop() { if (Serial.available() > 0) { String message = Serial.readStringUntil('\n'); message.trim(); if (isNumber(message) and message.length() == 32) { char charArray[33]; message.toCharArray(charArray, 33); Serial.print("What enter the function: "); Serial.println(charArray); pakiet = readBinaryString(charArray); Serial.print("Thats exit the function: "); Serial.println(pakiet); Serial.print("Thats the reverse of the function: "); Serial.println(longToBinaryString(pakiet)); } if (isNumber(message) and message.length() == 32) { Serial.print("What enter the function: "); Serial.println(message); pakiet = binaryToLong(message); Serial.print("Thats exit the function: "); Serial.println(pakiet); Serial.print("Thats the reverse of the function: "); Serial.println(longToBinaryString(pakiet)); } } }
我在Arduino中实现了两种32位二进制字符串转long的方法:基于char数组的readBinaryString,以及基于String类的binaryToLong,同时用longToBinaryString实现long转32位二进制字符串的逆向验证。
输入二进制字符串11111111000011111111111111000011时,两种方法结果差异明显:
readBinaryString转换结果为-15728701,逆向转换后与原输入一致;binaryToLong转换结果为-1089471104,逆向转换后得到10111111000011111111110110000000,与原输入不符。
结果不同的原因
binaryToLong的问题出在使用了pow()函数。pow()是浮点数运算函数,而long是整数类型。当计算pow(2, n)(尤其是n接近31时),浮点数无法精确表示大整数,会产生精度误差。比如pow(2,31)的计算结果可能不是精确的2147483648,而是一个近似值,转成long时就会出错。再加上用+=累加这些不精确的值,最终结果完全偏离正确值。
而readBinaryString采用位运算:每次将结果左移1位(等价于乘以2),遇到'1'就给最低位设为1。整个过程都是整数操作,没有精度损失,因此结果正确。
修正后的binaryToLong函数
将binaryToLong改成位运算实现,逻辑与readBinaryString一致,适配String类:
long binaryToLong(String binaryString) { long result = 0; for (int i = 0; i < binaryString.length(); i++) { result <<= 1; // 左移一位,等价于乘以2 if (binaryString.charAt(i) == '1') { result |= 1; // 最低位设为1 } } return result; }
修正后,该函数的转换结果与readBinaryString完全一致,逆向转换也能得到原输入的二进制字符串。
内容的提问来源于stack exchange,提问作者MarcinanBarbarzynca
相关产品推荐
相关产品推荐

