long long signed A, B, C;
或
long long unsigned A, B, C;
我需要计算表达式A * B / C
的商和余数,其中A
,B
,C
是大整数,因此产品A * B
会导致溢出并A < C
和B < C
。禁止使用浮点数和使用第三方库。怎么做?
答案 0 :(得分:3)
A*B/C
的余数等于余数A/C
和B/C
模C
的乘积。
//编辑:上传,看不到条件A<C
,B<C
。在这种情况下尝试这样的事情:
tmp = A;
for (var i = 1; i<=B; i++)
{
if (tmp + A == overflow || tmp + A >= C)
tmp -= C;
tmp += A;
}
结果tmp
应该是您寻求的余数。只要所有输入都是正数,我们就会在签名情况下这样做。也许它对无符号也有用,但是没有检查它。
当然,您需要一些奇特的功能来检查oveflow
条件。
至于商,您只需评估A/C
,然后将其乘以B
,不是吗?
答案 1 :(得分:3)
使用任意大整数进行乘法非常简单:你完全像在scool时那样做,并在纸上手工完成。但是,不是在基数10中使用十进制数,而是使用字节或整数。
例如:
A = 12340;
B = 56789;
aa = new byte[] { A/256, A%256 };
bb = new byte[] { B/256, B%256 };
现在你可以遍历数组并以较小的步长进行乘法。
答案 2 :(得分:1)
我认为一个好的开始应该是使用带有gmp的c / c ++。 gmp是一个任意精度库,它具有为任意精度实现的所有这些操作。它适用于整数和浮点数。
编辑:(没有第三方库)
我的第二个虽然关于它(在gmp之后)是素数分解。你需要一个算法。您可以使用Afactorization,Bfactorization和Cfactorization创建一个向量,该向量具有分解的素数列表。然后你测试A / B的素数与C中的素数,并开始删除它们的A / B和C矢量。在对所有这些元素进行测试之后,将所有向量的成员相乘并进行正常除法。
答案 3 :(得分:1)
对于没有64位算术的32位数乘法,有Schrage的方法。也许你可以把它扩展到64位乘法。
答案 4 :(得分:1)
你必须将A和B分成上下32位部分
A = Au * (1<<32) + Al
B = Bu * (1<<32) + Bl
(计算为Au=A>>32; Al=A&(1<<(32)-1;
)并分别考虑这些部分的产品:
A*B = Au*Bu * (1<<64) + (Au*Bl+Al*Bu) * (1<<32) + Al*Bl
接下来你必须将每个术语除以C并累加商和余数(小心避免溢出!)。特别是,由于您的初始要求,Au * Bu> C是不可能的。
答案 5 :(得分:1)
例如:
typedef long long ll;
const ll base = 1000*1000*1000; // 10^9 for example, could be also 1<<32
// or smth convenient, the goal is to store
// the numbers and a result in 'base'-based numerical system
// to avoid overflow
pair<ll, ll> p1 = make_pair( A/base, A%base ); // store the numbers in
pair<ll, ll> p2 = make_pair( B/base, B%base ); // 'base'-based numerical system
vector<ll> v1(4);
v1[ 0 ] = p1.second * p2.second;
v1[ 1 ] = p1.first * p2.second + v1[ 0 ] / base; v1[ 0 ] %= base;
v1[ 2 ] = v1[ 1 ] / base; v1[ 1 ] %= base;
vector<ll> v2(4);
v2[ 1 ] = p1.second * p2.first;
v2[ 2 ] = p1.first * p2.first + v2[ 1 ] / base; v2[ 1 ] %= base;
v2[ 3 ] = v2[ 1 ] / base; v2[ 2 ] %= base;
ll tmp = 0;
for( i = 0; i < 4; ++i )
{
v1[ i ] = v1[ i ] + v2[ i ] + tmp;
tmp = v1[ i ] / base;
v1[ i ] %= base;
}
现在v1存储以基数10 ^ 9表示的A * B的值。剩下的就是仔细地将它划分为C,这是一个简单的数学挑战:)