作为一名测绘专业的学生,在内业计算中经常遇到遇到小数点后保留几位小数的问题。根据《工程测量实验教程》(王宇会 著)一书,内业计算按“四舍六入,五前单进双舍(或称奇进偶不进)”的取舍规则进行尾数的取舍。如数据1.1235和1.1245小数点后保留三位时,均应为1.124
//四舍六入五成双的基于C++11的实现
//C++11中sprintf、strncpy由于VS2015会报错,所以在这里改用sprintf_s、strncpy_s
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
const int n = 1000; //设置要保留的位数
char s1[20];
char s2[20];
int main()
{
double a1, a2, a3;
cin >> a1;
a2 = a1*n; //将输入的数据乘以n,使得小数点后的第一位使我们要判断的是否为5的数
sprintf_s(s1, "%lf", a2); //将double类型的a2打印到字符数组s1里面去
int b = strcspn(s1, "."); //整型b即为小数点在字符数组中序号
char c = s1[b + 1]; //字符c即为小数点后一位数
if (c<'5') //如果c小于5,则后面的舍去
{
strncpy_s(s2, s1, b);
a3 = atof(s2);
}
else
{
if (c>'5') //如果c大于5,则进1
{
strncpy_s(s2, s1, b);
a3 = atof(s2) + 1;
}
else
{
//如果c大、等于5,则对前一位数进行判断奇偶
c = s1[b - 1];
if ((c % 2) != 0) //C前一位为奇则进1
{
strncpy_s(s2, s1, b);
a3 = atof(s2) + 1;
}
else
{
strncpy_s(s2, s1, b);
a3 = atof(s2);
}
}
}
a3 = a3 / n;
cout << a3 << endl; //输出结果
return 0;
}
//四舍六入五成双的C++实现
虽然实现了这个功能,不过有时候觉得还是很难用,所以将上面的程序封装成函数
//四舍六入五成双的基于C++11的实现封装成函数
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
double SSLR(double s1, int a)
{
int n;
switch (a)
{
case 1:
n = 10; break;
case 2:
n = 100; break;
case 3:
n = 1000; break;
default:
n = 1;
break;
}
//设置要保留的位数
double s2 = s1*n; //将输入的数据乘以n,使得小数点后的第一位使我们要判断的是否为5的数
double s3;
char c1[20];
char c2[20];
sprintf_s(c1, "%lf", s2); //将double类型的a2打印到字符数组s1里面去
int b = strcspn(c1, "."); //整型b即为小数点在字符数组中序号
char c = c1[b + 1]; //字符c即为小数点后一位数
if (c<'5') //如果c小于5,则后面的舍去
{
strncpy_s(c2, c1, b);
s3 = atof(c2);
}
else
{
if (c>'5') //如果c大于5,则进1
{
strncpy_s(c2, c1, b);
s3 = atof(c2) + 1;
}
else
{
//如果c大、等于5,则对前一位数进行判断奇偶
c = c1[b - 1];
if ((c % 2) != 0) //C前一位为奇则进1
{
strncpy_s(c2, c1, b);
s3 = atof(c2) + 1;
}
else
{
strncpy_s(c2, c1, b);
s3 = atof(c2);
}
}
}
s3 = s3 / n;
//cout << s3 << endl; //输出结果
return s3;
}
int main()
{
double d1, d2, d3;
cin >> d1;
d2=SSLR(d1);
cout << d2 << endl;
return 0;
}
/***手动分割线 2018.5.1修改***/
其实上面的SSLR函数代码也可以根据不同的需要来进行修改。
参加过一次测绘程序程序设计竞赛后,便发现这个程序还不够完善,因为double类型默认输出位数只有六位,保留三位小数后超出了六位输出就会出问题(我是在计算前方交会的时候遇到的),便只好用头文件iomanip里的setprcision来解决了
#include <iostream>
#include "shuce.h"
#include <iomanip>
#include <string.h>
//#include <string>
using namespace std;
int main()
{
char c[16];
long double s;
cin >> s;
double s1=SSLR(s, 3);
sprintf_s(c,"%lf",s1);
//int l0 = strlen(c);
int l = strcpy_s(c,".");
cout << s << endl;;
cout << fixed<<setprecision(l+3)<<s1 << endl; //注意l+3这里,加的数值应与前面保留的位数相对应
//cout << s;
return 0;
}
欢迎各位留言提意见