[ESP8266在做小的双精度数学运算时是ovf]

问题描述 投票:1回答:2

我正在使用基于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 esp8266
2个回答
0
投票

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讨论了如何做到这一点。


-2
投票

浮点数可以大至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),但是大的正数需要无符号长。

© www.soinside.com 2019 - 2024. All rights reserved.