C++四舍五入保留N位小数
来源:互联网 发布:维修基金算法 编辑:程序博客网 时间:2024/05/24 04:10
最近遇到这个问题,不难吧,不过搜网上的东西,没看到比较合心水的答案,自己搞了两种做法,请君侧耳为我听。
乘10法
这种想法最容易想到,就是将数字乘10,乘N次,加上0.5后取整,最后再除回去。加上0.5取整应该很容易理解,是等价于四舍五入的,因为X.49999……+0.5后取整是不会进位的,结果是X;而X.5000……1+0.5后取整会变成X+1(当然忽略double或float能表示的精度)。
比如:
23.3451保留两位小数,那么连续乘10,2次,得到2334.5,加上0.5后取整得到23345,再除回去,变成23.35,是不是对了呢?
简单代码如下:
#include <stdio.h>#include <cmath>typedef long long LL;double round(double number, unsigned int bits) { LL integerPart = number; number -= integerPart; for (unsigned int i = 0; i < bits; ++i) number *= 10; number = (LL) (number + 0.5); for (unsigned int i = 0; i < bits; ++i) number /= 10; return integerPart + number;}int main() { printf("%.2f\n", round(23.451528739, 1)); printf("%.3f\n", round(23.451528739, 2)); printf("%.4f\n", round(23.451528739, 3)); printf("%.5f\n", round(23.451528739, 4)); printf("%.6f\n", round(23.451528739, 5)); printf("%.7f\n", round(23.451528739, 6)); printf("%.8f\n", round(23.451528739, 7)); return 0;}
注意,printf也可以做到按多少位小数四舍五入输出,所以在输出的时候,我总是把printf输出的精度比我自己的函数高1个位,可以看出那个位总是为0,表示是我写的函数起的作用(而不是printf的影响),上面的示例程序的输出结果为:
23.50
23.450
23.4520
23.45150
23.451530
23.4515290
23.45152870
问题来了
这个做法有什么问题呢?
注意到上面是先将double的整数部分保留起来了,然后后面只是对number原来的小数部分乘以10而已,为什么要这样做呢?
因为,注意到后面做四舍五入的关键一步,要取整,如果不先把已知的整数部分去掉,那么总体乘以10^N后很容易就会溢出整数所能表示的范围了!
也就是说,这种方法的局限在于,需要将double转成数值范围相对很小的long long来表示,所以如果需要精确到很大的小数位的话,就坑了,因为long long最多能表示10^18左右的数字,如果想四舍五入到小数点后20+位的话……其实这样变态的需求一般不会有,而且也不可能会有,因为double本身的精确位数只能到15-16(参考:float与double的范围和精度)。
再者,注意原始的整数部分也是用long long来保存的,这样对于double的范围几乎就限制死了……有没有更好的方法呢?
会这样问的,肯定就是有啦,我发现可以使用cmath库的floor向下取整函数来辅助取整,而不需要通过long long类型来取整,这样的话,上面所说的两个约束就不存在了!!!
double round(double number, unsigned int bits) { double integerPart = floor(number); number -= integerPart; for (unsigned int i = 0; i < bits; ++i) number *= 10; number = floor(number + 0.5); for (unsigned int i = 0; i < bits; ++i) number /= 10; return integerPart + number;}
使用C++的输出流功能
C++的输出流可以通过setprecision(N)和fixed合作来进行精确到小数点后第N为四舍五入!
但是只能输出到控制台???我想做成像上面那样的一个函数,结果作为返回值返回。
这个时候简单借助stringstream就好了!!!示例如下:
#include <iostream>#include <sstream>#include <iomanip>using namespace std;double round(double number, unsigned int bits) { stringstream ss; ss << fixed << setprecision(bits) << number; ss >> number; return number;}int main() { double number = 3.1415926535897932; cout << fixed << showpoint << setprecision(15); cout << "一开始number = " << number << endl; for (int i = 0; i < 15; ++i) { cout << "number保留" << i << "位小数后为: " << round(number, i) << endl; } return 0;}
输出为:
一开始number = 3.141592653589793
number保留0位小数后为: 3.000000000000000
number保留1位小数后为: 3.100000000000000
number保留2位小数后为: 3.140000000000000
number保留3位小数后为: 3.142000000000000
number保留4位小数后为: 3.141600000000000
number保留5位小数后为: 3.141590000000000
number保留6位小数后为: 3.141593000000000
number保留7位小数后为: 3.141592700000000
number保留8位小数后为: 3.141592650000000
number保留9位小数后为: 3.141592654000000
number保留10位小数后为: 3.141592653600000
number保留11位小数后为: 3.141592653590000
number保留12位小数后为: 3.141592653590000
number保留13位小数后为: 3.141592653589800
number保留14位小数后为: 3.141592653589790
分析一下,这个输出流的功能是C++的标准库支持的,所以其可靠性是可以信任的,没有上面的做法那么多控制的考虑。
问题来了
它库是怎么实现的????
真心好奇,希望有知道的朋友发邮件告诉我一声,万谢!
不然我只能等有空去找源码看了^_^
- 四舍五入,保留N位小数
- java四舍五入、保留n位小数
- Java 四舍五入 保留N位小数
- java四舍五入、保留n位小数
- C++四舍五入保留N位小数
- 金额四舍五入保留n位小数
- 使Decimal类型数据保留N位小数且不进行四舍五入操作(C#)
- JS中保留N位小数,四舍五入函数
- Java使四舍五入和保留N位小数的方法
- 四舍五入保留两位小数
- 四舍五入保留两位小数
- C语言double保留N位小数
- java 小数四舍五入 保留两位小数
- 将数字四舍五入保留两位小数
- java 四舍五入后保留两位小数
- 保留两位小数即四舍五入
- 新JS四舍五入保留两位小数
- JS保留两位小数 四舍五入函数
- C#反射的Assembly的简单应用
- Multipath TCP
- Http协议详解
- 使用proc接口例子
- UVA 11825 Hackers' Crackdown(枚举子集+dp)
- C++四舍五入保留N位小数
- 第二周项目1-C/C++语言中函数参数传递的三种方式
- halcon学习笔记(4)——调用图形函数画Region
- After the first attempt in IA
- VS2015上配置opencv2.4.11
- 常用排序算法总结8一一基数排序
- window对象的常用方法
- 多路径 TCP
- numpy.Scalars