【问题标题】:Limit floating point precision?限制浮点精度?
【发布时间】:2010-08-01 21:29:09
【问题描述】:

有没有办法将浮点数舍入到 2 点?例如:3576.7675745342556 变为 3576.76

【问题讨论】:

  • 你的意思是显示还是计算?
  • 3576.7675745342556 变成了 3576.77,不是吗?
  • @Vladimir: 没有必要。舍入是一个模糊的术语,它封装了几个具有更确切含义的不同操作。向上/向下/向零/向无穷大/向最近的整数等舍入。

标签: c++ c algorithm floating-point floating-point-conversion


【解决方案1】:
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)); 
}

【讨论】:

  • 请注意,由于二进制浮点数不能准确表示大多数十进制值,因此当您开始仔细检查低位数字时,此答案将不起作用。但话又说回来,其他任何答案都没有。
  • 为什么在更灵活的版本中使用floor而不是round
  • value * pow(10, precision) + 0.5 方法失败 1) 许多负值,2) 加法在中途情况下会导致不精确,3) 乘法溢出。
【解决方案2】:

如果您将其打印出来,请改用您可用的任何打印格式功能。

在 C++ 中

cout << setprecision(2) << f; 

对于渲染到 GUI 的舍入,使用 std::ostringstream

【讨论】:

  • 永远不要用“如上所述”引用另一个答案。显示答案的顺序会随着时间和用户可配置的偏好(按时间或投票数排序)而变化。为了解决您的特定问题,可以使用 floorceil 代替整数转换。
  • @Svante ,因为我们使用的是 C++?
  • 虽然 cout 在 C++ 中可能是首选,但您可以在 C 或 C++ 中使用 printf。例如。 std::printf("Printf C++\n");
  • 我的意思是printf("%.2f", f);
  • #include 这是什么?
【解决方案3】:

乘以 100,四舍五入到整数(随心所欲),除以 100。请注意,由于 1/100 不能用浮点数精确表示,请考虑保留固定精度整数。

【讨论】:

  • 十进制定点整数很可能是这里真正的正确答案。
【解决方案4】:

对于那些像我一样在谷歌上搜索格式化浮点数的人:

#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"

您必须将其作为字符串返回。将其放回浮点数将失去精度。

【讨论】:

    【解决方案5】:

    不要使用浮点数。如果要打印美元,请使用整数存储美分数并在最后 2 位之前打印小数点。浮点数对于金钱而言几乎总是错误,除非您进行简单的计算(如简单的经济数学模型),其中只有数字的大小才是真正重要的,而您从不减去附近的数字。

    【讨论】:

      【解决方案6】:

      尝试使用

      std::cout&lt;&lt;std::setprecision(2)&lt;&lt;std::cout&lt;&lt;x;

      应该可以工作,并且浮点数后只出现 2 位数字。

      【讨论】:

        【解决方案7】:

        我没有找到令我满意的干净答案,因为大多数干净答案都假设您需要打印结果,如果您只是将一些数据存储到可接受的分辨率,情况可能并非如此:

        #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-ReinstateMonica 我制作了stringstream static 以在一定程度上降低成本并删除了令人困惑的评论。干杯
        【解决方案8】:

        限制精度:
        如果 x 是浮点数,则不进行四舍五入:
        (上移两位小数,去掉小数,下移两位小数)

        ((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 是 floatdouble,所以小数部分将始终存在。这是 # 的表示方式 (IEEE 754) 和 # 的精度之间的区别。
        C99支持round()

        【讨论】:

        • 当产品超出 int 范围时,(int)(x*100.0) 失败。即使使用intmax_t 也是不够的。 x*100.0 + 0.5Fthis 一样失败。
        【解决方案9】:

        试试这个,效果很好

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

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

        【讨论】:

          猜你喜欢
          • 2021-11-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-31
          • 2018-07-06
          • 2017-11-30
          • 2019-11-10
          相关资源
          最近更新 更多