[英]Find the kth digit after the decimal point of a fraction a/b with a,b,k being very large integers (less than 10e18)
I was tasked to find a digit of kth position after the decimal point of a fraction(a/b).我的任务是在分数 (a/b) 的小数点后找到第 k 个数字 position。 Yesterday I found out this algorithm.
昨天我发现了这个算法。
To get any digit after the decimal point, I generate a variable called rem and make a loop为了获得小数点后的任何数字,我生成了一个名为 rem 的变量并进行了循环
for (int i = 1; i <= k+1; i++)
{
rem = a%b;
a = rem*10;
}
cout << a/b;
the loop will return a value being the kth digit after the decimal point.循环将返回一个值,该值是小数点后的第 k 个数字。
However the task require me to calculate with a,b,k being very large number ( less or equal to 10e18), so it's sure that the code will exceed the time limit.但是这个任务要求我用a,b,k计算非常大的数(小于或等于10e18),所以代码肯定会超过时间限制。
What your for loop calculates is effectively 10 * (a*10 k % b) / b. 您的for循环计算的有效值为10 *(a * 10 k %b)/ b。 We can do this more efficiently by doing exponentiation by squaring.
我们可以通过平方求幂来更有效地做到这一点。 We have to be careful not to overflow at every point though:
但是,我们必须注意不要在每个点上都溢出:
int kth_digit_frac(uint64_t a, uint64_t b, uint64_t k) {
return 10 * mulmodu64(a, powmod(10, k, b), b) / b;
}
// a*b % m, overflow safe
inline uint64_t mulmodu64(uint64_t a, uint64_t b, uint64_t m) {
#if defined(__GNUC__) && defined(__x86_64__)
uint64_t q, r;
asm("mulq %3;"
"divq %4;"
: "=a"(q), "=d"(r)
: "a"(a), "d"(b), "rm"(m)
: "cc");
return r;
#else
a %= m;
b %= m;
// No overflow possible.
if (a == 0) return 0;
if (b <= std::numeric_limits<uint64_t>::max() / a) return (a*b) % m;
uint64_t res = 0;
while (a != 0) {
if (a & 1) {
if (b >= m - res) res -= m;
res += b;
}
a >>= 1;
if (b >= m - b) b += b - m;
else b += b;
}
return res;
#endif
}
// b^e % m, overflow safe
inline uint64_t powmod(uint64_t b, uint64_t e, uint64_t m) {
uint64_t r = 1;
b %= m;
while (e) {
if (e % 2 == 1) r = mulmodu64(r, b, m);
b = mulmodu64(b, b, m);
e >>= 1;
}
return r;
}
It runs in the blink of an eye for any a,b,k
that fit in 64 bit integers. 眨眼之间就可以找到适合64位整数的任意
a,b,k
。
I believe two of the solutions above is still incorrect, because of a little error.我相信上面的两个解决方案仍然不正确,因为有一点错误。
I think the following will work nicely:我认为以下内容会很好地工作:
10 * (a*10^(k-1) % b) / b
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.