c++ - 用于 int -> float -> int 往返转换的舍入

标签 c++ c floating-point rounding

我正在为数据库引擎编写一组数字类型转换函数,我担心将大型整型浮点值转换为精度更高的整数类型的行为。

以将 32 位 int 转换为 32 位单精度 float 为例。 float 的 23 位有效位产生大约 7 位十进制数字的精度,因此转换任何超过 7 位的 int 将导致精度损失(这很好并且符合预期)。但是,当您将这样的 float 转换回 int 时,您最终会在低位数字中得到其二进制表示形式的伪像:

#include <iostream>
#include <iomanip>

using namespace std;

int main()
{
    int a = 2147483000;
    cout << a << endl;
    float f = (float)a;
    cout << setprecision(10) << f << endl;
    int b = (int)f;
    cout << b << endl;

    return 0;
}

这打印:

2147483000
2147483008
2147483008

尾随的 008 超出了 float 的精度,因此似乎不希望保留在 int 中,因为在数据库应用程序中,用户主要关心十进制表示,而尾随 0 用于表示无关紧要的数字。

所以我的问题是:是否有任何众所周知的现有系统在 float -> int(或 double -> long long)转换中执行十进制有效数字舍入,并且是否有任何众所周知的有效算法可以这样做?

(注意:我知道某些系统具有十进制浮点类型,例如由 IEEE 754-2008 定义的那些。但是,它们没有主流硬件支持,也没有内置到 C/C++ 中。我可能想在以后支持他们,但我仍然需要直观地处理二进制 float 。)

最佳答案

std::numeric_limits<float>::digits10说你只能得到 6 个精确的 float 。

为您的语言、处理器和数据分发选择一个有效的算法 calculate-the-decimal-length-of-an-integer (或 here )。然后减去digits10的位数说是精确地得到要剔除的位数。使用它作为索引来查找 10 的幂以用作模数。等等

一个问题:假设您将 float 转换为小数并执行此类舍入或截断。然后使用相同的舍入/截断方案将该“调整后的”小数转换为 float 并返回小数。你得到相同的十进制值吗?希望是的。

这不是您真正要找的东西,但阅读起来可能很有趣:A Proposal to add a max significant decimal digits value to the C++ Standard Library Numeric limits

关于c++ - 用于 int -> float -> int 往返转换的舍入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1883385/

相关文章:

c - 自由(): invalid next size (fast) in C

c - GetOutputStatus 说输出准备好了,ProcessOutput 说 NEED_MORE_INPUT

c - wprintf 不打印特殊字符,当 1 为 Fund 时,fgetws 返回 NULL

C++11:除非发布者休眠,否则发布者/消费者模式不会完成

c++ - 尝试实现 HeapSort

c++ - 错误 LNK2019 : unresolved external symbol "public: __thiscall : constructor issue

C 中 float 和 double 的比较

Python,在输出中将所有 float 打印到小数点后 2 位

javascript - 理解浮点变量

c++ - 当我按 enter 时程序不会继续