我正在使用基于ESP8266 wifi芯片的Wemos D1和Arduino C框架来做一些简单的小数学运算。据我所知,双精度是可用的,所以我正在使用它-最大值约为1.8 * 10 ^ 103。但是,当我尝试计算5 * 10 ^ 8附近的数字时,我得到了ovf。有什么想法吗?
void setup(){
Serial.begin(9600);
while(!Serial);
Serial.println("Hit any key to start math");
double te = 6800;
double res = te * te;
Serial.println(res);
te = 68000;
res = te * te;
Serial.println(res);
te = 680000;
res = te * te;
Serial.println(res);
}
void loop(){
}
打印
46240000.00
ovf
ovf
Arduino确实支持4字节双精度数据类型。并且您的代码确实产生了一个有效的double值,该值不是溢出(ovf)。
您看到的问题与Arduino实现Serial.print()
功能的方式有关,该功能几乎像半熟的hack来支持浮点,并且不如标准c / c ++中的vprintf()
可靠stdlib。您可以看到源代码here,该源代码打印的ovf
大于4294967040.0或小于-4294967040.0。出于兼容性原因,ESP8266 Arduino Core似乎继承了Arduino Serial.print()
的丑陋实现。
幸运的是,ESP8266 Arduino Core确实具有Serial.prinf()
方法,该方法支持更好的浮点渲染。此代码将显示您的号码确实是双精度数据类型的有效号码。
void setup(){
Serial.begin(9600);
while(!Serial);
double te = 68000;
double res = te * te;
Serial.println(res); //this will produce 'ovf'
Serial.printf("Result=%f\n", res); //this will produce correct 4624000000.000000
}
[请注意,Serial.prinf()
是ESP8266的特定实现,以支持标准库中的完整浮点vprintf()
。它不适用于标准Arduino开发板。
[对于Arduino板,有一种方法可以使用sprintf()
,它继承自vprintf()
,以在编译期间在链接器选项上稍加改动地打印正确的浮点。我有一篇博客文章Do you know Arduino - sprintf() and floating point讨论了如何做到这一点。
浮点数可以大至3.4028235E + 38,而低至-3.4028235E + 38。它们存储为32位(4字节)的信息。双精度浮点数。占用4个字节。Arduino上的double实现当前与float完全相同,但精度没有提高。无符号长变量是数字存储的扩展大小变量,并存储32位(4字节)。与标准long不同,无符号long不会存储负数,其范围为0到4,294,967,295(2 ^ 32-1)。长型变量是用于数字存储的扩展大小变量,并存储32位(4字节),范围从-2,147,483,648到2,147,483,647。整数是数字存储的主要数据类型,并且存储2字节的值。这将产生-32,768到32,767的范围(最小值为-2 ^ 15,最大值为(2 ^ 15)-1)。如果您不需要十进制值(即0.11),但是大的正数需要无符号长。