1. 程式人生 > >【測繪專用】四捨六入五成雙的C++實現

【測繪專用】四捨六入五成雙的C++實現

作為一名測繪專業的學生,在內業計算中經常遇到遇到小數點後保留幾位小數的問題。根據《工程測量實驗教程》(王宇會 著)一書,內業計算按“四捨六入,五前單進雙舍(或稱奇進偶不進)”的取捨規則進行尾數的取捨。如資料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;
}



歡迎各位留言提意見