2017-10-15 147 views
0

我试图在num中打印2个小数点的Cpp平均值。 avgfloatsumfloat,countint舍入到小数点后第二位,除非数字是整数C++

目前如果我有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。

+0

更新*显著*变化的问题。它不再要求*“舍入”*,而是*“截断”*。当然,这仍然算作四舍五入(无论是趋向于零还是负无穷),但是当他们孤立地看到术语*“四舍五入”时,并不是人们通常所期望的。更正:这不是更新改变了问题。截断要求从一开始就存在。建议的答案没有解决这个问题。当在“3.1467665”上运行时,它会产生“3.15”。 – IInspectable

回答

3

您可以根据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.14 3.1421783921,而不是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 -> 2.5
  • 10/3 -> 3.33
  • 10/2 -> 5
  • 10/7 -> 1.42
  • 3.9999 -> 3.99
+0

如果有一种方法可以使用旧的标准(在c11之前)来重写,它会很棒。无论如何,我会接受这个答案。非常感谢你。 –

+1

你可以用一个简单的整数转换替换昂贵的'modf'调用,例如'auto precision =(int(avg)!= avg)? ...:...;',给出'avg'支持的值范围,选择合适的整数类型。 – IInspectable

+0

那么当我希望它是27.5时,输出是27.50。有没有办法做到这一点? –

相关问题