计算浮点数

时间:2010-01-27 23:54:41

标签: c++ floating-point floating-accuracy frame-rate

我正在学习一些关于OpenGL的初学者教程,但是当我从一个c#程序员开始时,它让我把很多事情视为理所当然。所以我的问题出现在我调试打印输出的FPS读数时。我认为这个方法就像DebugPrintString一样脱离了我的头脑,它带了一个char *,基本上我打印的是“FPS:x”。我使用scanf_s将fps值放入字符数组中,但这就是我的问题所在。字符数组必须有多大?

让我详细说明一下:我的FPS读数存储为浮点数,因为帧/秒通常最终不是一个好数字。所以我的数字可能是60,或者可能是59.12345。 60只需要2个字节,59.12345需要8个(期间为1个)。所以我想“哦,我需要计算它的数字位数,没问题!”男孩是我的震惊。

我做了一个计算数字的方法,计算小数位的左边很容易,首先把它作为一个int去除小数点并除以10(实际上我觉得我有一些位移然后计算我可以做到的次数,直到我达到0.现在计算右边的数字,好吧我只需乘以10,减去数字,然后这样做直到它达到零。该方法通常会返回32我认为它是。所以我WTF并在调试中查看它,当你将浮动有效地移动数字列时,由于众所周知的精度问题,它只是附加了另一个数字!

我做了一些主要的谷歌搜索,但是无法在char str [128]和scanf上找到任何东西,如果在那时做strlen(str)减1(null终止符)。但我希望有一个更优雅的解决方案。最后我只是把它作为一个int并且允许足够9999 fps,还添加了一个检查以查看fps> 9999但我认为这不会发生。比SEG FAULT更安全:(

TLDR:有没有办法获得浮点数的位数? scanf如何做到这一点?!

很抱歉很长的帖子,只想分享我的挫折>:D

编辑:拼写错误

5 个答案:

答案 0 :(得分:7)

考虑到我们正在讨论的是C ++,为什么不采用STL方式呢?

精确到小数点后5位,可能是可变数量的字符:

std::stringstream ss;
ss << std::setprecision (5) << std::fixed << f; 
std::string fps = ss.str();

精确度最高5位有效数字:

std::stringstream ss;
ss << std::setprecision (5) << f; 
std::string fps = ss.str();

答案 1 :(得分:6)

您可以使用sprintf截断/强制浮点数到您想要的任何精度。然后问题就消失了。

答案 2 :(得分:1)

由于浮点数没有以任何精确的方式存储,因此实际上没有任何有效的方法来计算位数。您可能想要做的是控制float提供的数字的长度,并使用具有固定大小的缓冲区。

使用printf()scanf()和相关函数,可以通过修改格式类型说明符来指定浮点数的大小。虽然简单%f可能是最常见的,但可以通过在%f之间添加修饰符来更灵活地使用它,例如:

%[width][.precision]f

其中[width]是指为数字显示的最小位数(如果超过则不会截断),[.precision]指定确切的数字小数点后显示的数字。

举例来说,您可以检查以下程序的输出:

#include <cstdio>

using std::printf;
int main() {
  float f(59.12345);

  printf("[%f]\n", f);    // [59.123451]
  printf("[%15f]\n", f);  // [      59.123451]
  printf("[%1f]\n", f);   // [59.123451]
  printf("[%.2f]\n", f);  // [59.12]
  printf("[%6.2f]\n", f); // [ 59.12]
  printf("[%4.1f]\n", f); // [59.1]
}

字符数组的确切大小仍然可变,具体取决于小数点前的值。但只要你能控制宽度和精度,在字符数组中分配足够的内存(或将数字拟合成固定长度的数组)应该要简单得多。

答案 3 :(得分:0)

这是每秒帧数。只需使用左边的三个数字和右边的一个数字,谁关心浮点表示在十分之一的位置下发生了什么?

编辑以回应第一条评论。

http://en.wikipedia.org/wiki/Floating_point

如果我们真的在浮点数的位数之后,我们必须知道浮点数是如何工作的。 IEEE标准浮点数据类型中表示的确切值具有一定量的位,通常为32或64,它们以标准化方式分配给您一定数量的有效数字,以及一些幂指数来向上或向下扩展。 24位有效数字以小数形式出现在大约七位。在结束时总会出现某种形式的截断或舍入错误(例如,当你停止编写重复的三分之一时,三分之一,用十进制写的总是向下舍入)。

也许你的号码在七位或八位后停止,但是机器四舍五入错误会让它意外停止?阅读那种数据只是没有意义。

答案 4 :(得分:0)

约翰在CashCommons 给出了传统的答案,只需使用printf格式限定符来强制一定的宽度。我通常发现帧速率有2个小数位。它允许您区分30 fps和29.97 fps,这两个最常见的值。

 sprintf (buffer, "%.2f", fps);

但是如果你想知道最坏的情况是什么,那么这也是一种了解它的方法。结帐http://en.wikipedia.org/wiki/IEEE_754-2008

它表明浮点值(32位浮点数)在尾数中有24个二进制数字,可以达到7.225十进制数字,称之为8.为指数添加5位数,为符号添加1位,为前导添加1位数0,1为小数点,你得到

 1 + 1 + 8 + 5 = 15 characters

为终止空值添加空间,您将获得16位数字。