限制浮点数精度?

15

有没有一种方法将浮点数四舍五入到小数点后两位?例如:3576.7675745342556 变成 3576.76


4
你的意思是用于展示还是计算? - anon
2
3576.7675745342556 变成 3576.77,是吗? - Vladimir
2
@Vladimir: 不一定。 rounding 是一个模糊的术语,包括几种具有更确切含义的操作。向上/向下/向零/向正无穷/向最近整数等舍入操作。 - Martin York
9个回答

19
round(x * 100) / 100.0
如果必须使用浮点数:
roundf(x * 100) / 100.0

使用标准库函数的灵活版本:

double GetFloatPrecision(double value, double precision)
{
    return (floor((value * pow(10, precision) + 0.5)) / pow(10, precision)); 
}

3
请注意,由于二进制浮点数无法精确表示大多数十进制值,因此当您开始仔细检查较低位数字时,此答案将无效。但是同样地,任何其他答案也无法精确表示这些值。 - Mark Ransom
在更灵活的版本中,为什么要使用floor而不是round - pooya13
value * pow(10, precision) + 0.5 的方法存在以下问题:1)许多负数会失败;2)加法在中间情况下会产生不精确性;3)乘法会溢出。 - chux - Reinstate Monica

14
如果你要打印它,那么请使用可用的任何打印格式化函数。
在C++中
cout << setprecision(2) << f; 

对于要在GUI中进行四舍五入的情况,可以使用std::ostringstream。


5
请将文本从英语翻译成中文。仅返回翻译后的文本:不要引用“如上所述”的其他答案。答案的显示顺序随时间和用户可配置的首选项而变化(按时间或投票数排序)。为了解决您的特定问题,可以使用floorceil代替整数转换。 - Ben Voigt
1
@Svante,因为我们正在使用C++? - Craig
1
虽然在C++中可能更喜欢使用cout,但在C或C++中也可以使用printf。例如:std::printf("Printf C++\n"); - bn.
1
我的意思是 printf("%.2f", f); - Svante
这是什么 #include? - mLstudent33

3

将数值乘以100,四舍五入为整数(任何方式),再除以100。请注意,由于浮点数无法精确表示1/100,因此考虑使用定点整数。


1
十进制定点整数可能是这里的真正正确答案。 - caf

3

如果你像我一样想将浮点数格式化为货币形式,请参考以下内容:

#include <iomanip>
#include <sstream>
#include <string>

std::string money_format (float val)
{
    std::ostringstream oss;

    oss << std::fixed << std::setfill ('0') << std::setprecision (2) << val;

    return oss.str();
}
// 12.3456 --> "12.35"
// 1.2 --> "1.20"

你必须返回它作为一个字符串。将其转换回浮点数会损失精度。


2

不要使用浮点数。使用存储以美分为单位的整数,并在最后两位之前打印小数点,如果要打印美元。除非您进行简单的计算(如天真的经济数学模型),其中仅数字的大小真正重要且您从未减去附近的数字,否则浮点数几乎总是错误的


1

尝试使用

std::cout<<std::setprecision(2)<<std::cout<<x;

应该可以正常工作,只显示浮点数后的两位数字。


1

试试这个,它完美地工作。

float=3576.7675745342556;
printf("%.2f",float);

更改其中的一些对象以查看和学习代码。


1

我没有找到一个令我满意的干净答案,因为大多数干净的答案都假定你需要打印结果,但如果你只是将一些数据存储到可接受的分辨率,这可能并不是必需的:

#include <sstream>

template<typename T>
T toPrecision(T input, unsigned precision)
{
    static std::stringstream ss;

    T output;
    ss << std::fixed;
    ss.precision(precision);
    ss << input;
    ss >> output;
    ss.clear();

    return output;
}

template<unsigned P, typename T>
T toPrecision(T input) { return toPrecision(input, P); }

// compile-time version
double newValue = toPrecision<2>(5.9832346739); // newValue: 5.98
// run-time version
double newValue = toPrecision(3.1415, 2); // newValue: 3.14

你还可以为Tprecision(在编译时签名的情况下)添加静态检查。

虽然代价高昂,但在大多数情况下(如果不是所有情况),这种功能形式仍然是最佳答案,甚至可以处理大部分边缘情况。 - chux - Reinstate Monica
@chux-ReinstateMonica 我已经将 stringstream 设为 static 以减少成本,并删除了令人困惑的注释。干杯! - pooya13

0

为了限制精度:
如果x是一个浮点数,不进行四舍五入:
(向上移动2个小数位,去掉小数部分,向下移动2个小数位)

((int)(x*100.0)) / 100.0F

浮点数四舍五入:

((int)(x*100.0 + 0.5F)) / 100.0F

双精度无四舍五入:

((long int)(x*100.0)) / 100.0

带四舍五入的双精度:

((long int)(x*100.0 + 0.5)) / 100.0

注意:由于x是一个浮点数或双精度浮点数,因此小数部分始终存在。这是#表示法(IEEE 754)和#的精度之间的差异。
C99支持round()函数。

(int)(x*100.0)的乘积超出int范围时,会失败。即使使用intmax_t也不足以解决问题。x*100.0 + 0.5F的方法会像这样失败。 - chux - Reinstate Monica

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接