一、題目描述
輸入一個帶除法運算的字符串,輸出運算結果。其中,除不盡的,如果有循環小數,要用括號標識循環體。
輸入: 輸出:而不是
輸入: 輸出:(而不是
輸入: 輸出:
二、解題思路
這道題重點是怎麼找到循環節的位置。
- 我們知道,任意兩個自然數相除一定是無限循環小數
- 首先,先輸出結果的整數部分,這步很簡單,記得保存當前這步剩下的餘數
- 然後,我們可以維護一個
vector
,該vector
儲存當前的被除數。每次進行運算時,先將操作的被除數乘以,重複上述操作,得到一個新的餘數 - 到
vector
中去找現在得到的被除數是不是在裏面,如果不是,將這個數加入vector
,否則就說明找到了循環節,退出
三、解題代碼
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
bool VecFind(const vector<unsigned int> &vec, unsigned int num, int &loc){
loc = -1;
for (unsigned int i = 0; i < vec.size(); i++){
if (num == vec[i]){
loc = i;
return true;
}
}
return false;
}
void sln(unsigned int n, unsigned int m){
if (!m){
cout << "m can not be zero!" << endl;
return;
}
if (!n){
cout << 0 << endl;
return;
}
if (n % m == 0){
cout << n / m << endl;
return;
}
vector<unsigned int> vec, output;
if(n / m) //處理輸出.(3)而不是0.(3)的情況
cout << n / m;
cout << ".";
unsigned int cur_num = n / m, remain = n % m;
int find_cur_num = -1;
while (1){
auto cur_n = remain * 10;//當前操作數(被除數)爲上一步的餘數 * 10
cur_num = cur_n / m; //當前步得到的要輸出的數字
remain = cur_n % m; //當前步得到的餘數
if (VecFind(vec, cur_n, find_cur_num))
break;
else{
vec.push_back(cur_n);
output.push_back(cur_num);
}
}
for (unsigned int i = 0; i < find_cur_num; i++) //輸出循環節開始之前的小數數字,比如 7 / 6 = 1.1(3)
cout << output[i];
if (find_cur_num == output.size() - 1 && output[find_cur_num] == 0) {} //可以整除,不用輸出循環節,直接返回
else{
cout << "(";
for (unsigned int i = find_cur_num; i < output.size(); i++)
cout << output[i];
cout << ")";
}
cout << endl;
}
int main(){
unsigned int n, m;
while (scanf("%d/%d", &n, &m))
sln(n, m);
return 0;
}