1.原理
1.当两个整数相除,出现循环小数时,循环部分通常从某一点开始和前面的部分重复。
2.在竖式除法里小数部分的结果是由很多次整数除法得到的商组成的,剩下来的叫余数。
3.余数的第二次循环要比商的第二次循环早一个数,原因:商是由余数*10得到的下一个被除数再除以10。
4.余数的第二个循环的第一个数对应商第一个循环的末尾数。
5.再除数大于10的情况下商是会出现相同的数的,比如3/17=0.1764705882352941,但是余数不可能相同,余数*10是下一个被除数,而除数又是固定不变的,如果余数相同了,那么下一个余数也会和前面相同。这样必定已经循环了,所以余数是不可能相同了,相同了说明已经找到第一个循环节了。
6.(这一条要对应代码看,解释为什么不用vector)unordered_map有个find方法,返回一个迭代器,类似于指针,当进入下一个循环的时候它会停留在第一个数那里,不等于remainderMap.end(),其余情况remainderMap.find(remainder) == remainderMap.end()。使用vector可以把条件改为vec[i]!=vec[0]很方便,但是第一次进入循环的时候只有一个数字,必然会出现vec[i]==vec[0]的情况
2.代码
int main() {
//这两条看不懂不用管,可写可不写
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
//a是除数,b是被除数
int a, b;
std::cin >> a >> b;
//接收结果的字符串
std::string result = "";
std::unordered_map<int, int>remainderMap;
//整数部分
int integer = a / b;
//小数部分
int quotient = 0;//第一个商不重要
int remainder = a % b;//第一个余数
int position = 0;//用来凑键值对的
while (remainder && remainderMap.find(remainder) == remainderMap.end()) {
remainderMap[remainder] = position;
//补零的操作
a = remainder * 10;
//将商储存在字符串中
quotient = a / b;
result += std::to_string(quotient);//将数字转化为字符串
//得到余数
remainder = a % b;
//位置加一
position++;
}
//打印结果
std::cout << integer << '.';
std::cout << result << std::endl;
return 0;
}
模拟的逻辑:先进行一次取模操作,得到一个比除数小的数(第一个余数),进入while循环,步骤是这样的:先存余数,再补零,然后计算商,将商放入字符串,再计算下一个余数,位置++。
如果对你有帮助,给个三连吧。