C++ 标准库之 iomanip 、操作符 ios::fixed 以及 setprecision 使用的惨痛教训经验总结

本菜鸡自从退役之后就再也没怎么敲过 C++ 代码,在 C++ 语言下,求解关于浮点数类型的问题时,之前有碰到类似的情况,但是似乎都没有卡这块的数据,基本上用一个 setprecision 函数保留几位有效数字就 AC 了。但这次在计算任意五个数的平均值时卡在了一组数据上,问题如下:

#include <iostream>#include <iomanip>#include <stdio.h>using namespace std;int main(){ float a,b,c,d,e; cin>>a>>b>>c>>d>>e; float ave = (a+b+c+d+e)*1.0/5; //cout<<setiosflags(ios::fixed)<<setprecision(2)<<ave*1.0<<endl; cout<<setprecision(2)<<ave*1.0<<endl; //printf("%.2f",ave); return 0;}/* * Problem: 连续输入5个数,数的范围为0.00~2.00,输出其平均值,并保留两位小数。 ***//*用例:1.82 1.86 1.88 1.65 1.78对应输出应该为:1.80你的输出为:1.8***/

我们从头到尾来看看这段代码吧。

首先是头文件:#include

,我们可能没太见过,老实说我也是第一次见,以前都是用 C++ 那个总的头文件 #include<bits/stdc++.h> ,包含了
全部的C++头文件,所以很多小的头文件可能都不太记得。

关于 bits/stdc++.h 的源代码如下:

// C++ includes used for precompiling -*- C++ -*-// Copyright (C) 2003-2014 Free Software Foundation, Inc.//// This file is part of the GNU ISO C++ Library. This library is free// software; you can redistribute it and/or modify it under the// terms of the GNU General Public License as published by the// Free Software Foundation; either version 3, or (at your option)// any later version.// This library is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.// Under Section 7 of GPL version 3, you are granted additional// permissions described in the GCC Runtime Library Exception, version// 3.1, as published by the Free Software Foundation.// You should have received a copy of the GNU General Public License and// a copy of the GCC Runtime Library Exception along with this program;// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see// <http://www.gnu.org/licenses/>./** @file stdc++.h * This is an implementation file for a precompiled header. */// 17.4.1.2 Headers// C#ifndef _GLIBCXX_NO_ASSERT#include <cassert>#endif#include <cctype>#include <cerrno>#include <cfloat>#include <ciso646>#include <climits>#include <clocale>#include <cmath>#include <csetjmp>#include <csignal>#include <cstdarg>#include <cstddef>#include <cstdio>#include <cstdlib>#include <cstring>#include <ctime>#if __cplusplus >= 201103L#include <ccomplex>#include <cfenv>#include <cinttypes>#include <cstdalign>#include <cstdbool>#include <cstdint>#include <ctgmath>#include <cwchar>#include <cwctype>#endif// C++#include <algorithm>#include <bitset>#include <complex>#include <deque>#include <exception>#include <fstream>#include <functional>#include <iomanip>#include <ios>#include <iosfwd>#include <iostream>#include <istream>#include <iterator>#include <limits>#include <list>#include <locale>#include <map>#include <memory>#include <new>#include <numeric>#include <ostream>#include <queue>#include <set>#include <sstream>#include <stack>#include <stdexcept>#include <streambuf>#include <string>#include <typeinfo>#include <utility>#include <valarray>#include <vector>#if __cplusplus >= 201103L#include <array>#include <atomic>#include <chrono>#include <condition_variable>#include <forward_list>#include <future>#include <initializer_list>#include <mutex>#include <random>#include <ratio>#include <regex>#include <scoped_allocator>#include <system_error>#include <thread>#include <tuple>#include <typeindex>#include <type_traits>#include <unordered_map>#include <unordered_set>#endif

include

是 I/O 流控制头文件,类似与 C 里面的格式化输出一样,记住就好,具体的一些操作符及作用可以参考下表所示。

操作符作用
dec设置整数为十进制
hex设置整数为十六进制
oct设置整数为八进制
setbase(n)设置整数为n进制(n=8,10,16)
setfill(n)设置字符填充,c可以是字符常或字符变量
setprecision(n)设置浮点数的有效数字为n位
setw(n)设置字段宽度为n位
setiosflags(ios::fixed)设置浮点数以固定的小数位数显示
setiosflags(ios::scientific)设置浮点数以科学计数法表示
setiosflags(ios::left)输出左对齐
setiosflags(ios::right)输出右对齐
setiosflags(ios::skipws)忽略前导空格
setiosflags(ios::uppercase)在以科学计数法输出E与十六进制输出X以大写输出,否则小写
setiosflags(ios::showpos)输出正数时显示"+"号
setiosflags(ios::showpoint)强制显示小数点
resetiosflags()终止已经设置的输出格式状态,在括号中应指定内容

浮点数但是我们要记住的一点是,一个浮点数的有效数字位数默认为为 6 位,你可以通过 setprecision(n) 操作符来修改显示有效数字的有效数字的位数。但我们需要注意以下两个重要的易错点:

  • 如果有效数少于要显示的数字,则 setprecision 将舍去
  • 末尾的零将被省略

那我们如果想要根据我们自己的意愿输出小数点后相应的位数,我们又该怎么办呢?

C++ 在 iostream 头文件中定义了一个 ios::fixed 操作符,它可以使输出数据用小数点的形式打印在屏幕上。这样我们就可以人为的控制输出自己想保留小数点后相应的位数。

setiosflags(ios::fixed) 是定义在

中的函数,该操作符的作用是执行有参数指定区域内的动作,我们传入了参数 ios::fixed ,该参数指定的动作是以带小数点的形式表示浮点数,并且在允许的精度范围内尽可能的把数字移向小数点右侧。

例如我们还是拿上面那个例子来说:

cout<<ave*1.0<<endl; (1)cout<<setprecision(2)<<ave*1.0<<endl; (2)cout<<setiosflags(ios::fixed)<<ave*1.0<<endl; (3)cout<<setiosflags(ios::fixed)<<setprecision(2)<<ave*1.0<<endl; (4)

根据上面所描述的那样,我们很容易得出如下结果:

(1) = 1.798(2) = 1.8(3) = 1.798000(4) = 1.80

相关文章