【问题标题】:Rounding to second decimal place unless the number is whole c++舍入到小数点后第二位,除非数字是整数 c++
【发布时间】:2017-10-15 08:46:19
【问题描述】:

我正在尝试打印 Cpp 中的平均值,直到 float num 的小数点后 2 位。 avgfloatsumfloatcountint

目前,如果我有 10/1,例如它输出 10.00。我希望输出只有 10。例如,如果 avg 获得值 3.1467665,它应该显示为 3.14

avg = sum/count;
std::cout << std::fixed << std::setprecision(2) << avg;

四舍五入应该仅用于输出。 avg 不用改,如果方便的话,可以改一下值。

寻找使用c++11之前的标准的解决方案。

UPD:当我希望输出为 27.5 时,输出为 27.50。

【问题讨论】:

  • 更新显着改变了问题。它不再要求 "rounding",而是要求 "truncation"。当然,这仍然算作四舍五入(趋向零或负无穷大),但当人们孤立地看到 “四舍五入” 一词时,这并不是人们通常所期望的。更正:不是更新改变了问题。截断要求从一开始就存在。提议的答案没有解决这个问题。当与3.1467665 运行时,它将产生3.15

标签: c++ floating-point output rounding precision


【解决方案1】:

您可以根据avg 值的浮动模数选择精度。以下作品:

int main() {
  double sum = 10;
  double count = 3;
  double avg = sum/count;
  double mod;
  std::cout << std::fixed
            << std::setprecision((modf(avg, &mod) != 0.0) ? 2 : 0)
            << avg
            << std::endl;
}

考虑到添加的规范:

  • 用 2.5 代替 2.50
  • 为 3.1421783921 写 3.14,而不是 3.15

这是使用@IInspectable 建议的方法的可能实现:

  std::stringstream ss;
  ss << std::fixed << avg;

  size_t pos = ss.str().find('.');
  if (pos + 2 < ss.str().size()) // If there is a '.' and more than 2 digits after it
    pos += 3;
  std::string s = ss.str().substr(0, pos); // Leave only two digits

  s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) { return ch != '0'; }).base(), s.end()); // Remove trailing zeros
  s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) { return ch != '.'; }).base(), s.end()); // Remove trailing '.' when needed
  std::cout << s << std::endl;

这将输出:

  • 10/4 -&gt; 2.5
  • 10/3 -&gt; 3.33
  • 10/2 -&gt; 5
  • 10/7 -&gt; 1.42
  • 3.9999 -&gt; 3.99

【讨论】:

  • 如果有办法使用较旧的标准(c11 之前)重写它,那就太好了。无论如何,我会接受这个作为答案。非常感谢。
  • 您可以用简单的整数转换替换昂贵的 modf 调用,例如auto precision = (int(avg) != avg) ? ... : ...;,根据avg 的支持值范围选择适当的整数类型。
  • 当我希望输出为 27.5 时,输出为 27.50。有没有办法做到这一点?
  • @KarinaK:代码并非特定于 C++11。您必须做的唯一更改是拼出类型来代替auto。至于新要求,问题中没有要求。是的,这也是可能的。那时您可能应该考虑字符串操作:从具有 2 个小数位的值构造字符串表示形式;去除尾随零,直到没有;去掉结尾的 . 字符。该算法会产生所需的结果。
  • @IInspectable,在我的回答中添加了这样的实现
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-02-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多