我正在关注一些 C++ 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'd 并在调试中查看了它,结果发现,当您乘以浮点数时,由于众所周知的精度问题,有效地将数字列向上移动,它只是附加了另一个数字!

我做了一些主要的谷歌搜索,但找不到 char str[128] 和 scanf if in then do strlen(str) minus 1 (空终止符)之上的任何内容。但我希望有一个更优雅的解决方案。最后,我只是将其转换为 int 并允许足够的 9999 fps,还添加了一个检查以查看 fps > 9999,但我认为这不会发生。比 SEG FAULT 更安全:(

总而言之:有没有办法获取浮点数中的位数?scanf是怎么做到的?

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

编辑:拼写错误

有帮助吗?

解决方案

考虑到它的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();

其他提示

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

由于浮点数不存储在任何精确的方式,有没有真正计数的位数任何有效途径。你可能想要做的是控制所述浮球可提供数的长度,并使用一个缓冲器具有固定的大小。

使用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]
}

字符数组的确切大小将仍然取决于小数点前的值是可变的。但是,只要可以控制宽度和精度,分配足够的内存入一个字符数组(或嵌合的数量成固定长度的阵列)应该基本上简单。

出色地 约翰在 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

添加终止 null 的空间,您将得到 16 位数字。

每秒它的帧。只是在右边,谁在乎什么浮点表示碰巧觉得下面的十位存在使用左侧和一个三位数?

EDIT响应于第一评论

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

如果我们在浮动的位数之后真的,我们必须知道如何浮动工作。在IEEE标准float数据类型表示的精确值具有一定量的比特通常32或64,其在一个标准化的方法来给你的显著位数设定量分配的,以及一些幂指数或缩放上下。的显著位数24位出来,以小数约七宿。人们总是将是某种形式的截断或课程结束舍入误差(怎么样三分之一,用十进制,总是当你停止编写重复三分向下取整)。

也许你的号码后七位或八位数字停止,但机器舍入误差保持它会意外?它只是没有道理读取这种类型的数据。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top