C++ 方程中的多重/除法困境
我需要用C/C++计算这个方程:C++ 方程中的多重/除法困境,c++,c,C++,C,我需要用C/C++计算这个方程: x=(a*b-1)/c; 对于类型为_int64(a,b,c,x的a,b,c,x,如果您的代码依赖于CPU,最简单的方法可能是使用汇编程序保留高阶8字节。x64假设结果适合8字节: __asm{ MOV RAX, a MUL b SUB RAX, 1 SBB RDX, 0 DIV c MOV x, RAX } [1] 尝试计算a的最大乘数,它不会溢出。例如,如果a*4会溢出,则部分执行: (a*5) = (a*3) + (a*2)
x=(a*b-1)/c;
对于类型为_int64(a,b,c,x的a,b,c,x,如果您的代码依赖于CPU,最简单的方法可能是使用汇编程序保留高阶8字节。x64假设结果适合8字节:
__asm{
MOV RAX, a
MUL b
SUB RAX, 1
SBB RDX, 0
DIV c
MOV x, RAX
}
[1] 尝试计算a的最大乘数,它不会溢出。例如,如果a*4会溢出,则部分执行:
(a*5) = (a*3) + (a*2)
所以,如果你发现像
b1, b2, b3, where b1+b2+b3 == b
然后
您将从b1=floor(MAX_INT/a)中找到最大的可用值,然后只有在b-b1
(ax + b) * (cx + d)
= ac x^2 + (ad+bc) x + bd
[ab]*[cd]=[efg]:
//long long e,f,g
g = (long long)b*d;
f = (long long)a*d+b*c;
e = (long long)a*c;
//perform carry
f += g>>32; g &= 0xFFFFFFFF
e += f>>32; f &= 0xFFFFFFFF
学校划分,假设无符号算术:
[efg]/[hi]=[jkl]:
[jk] = [ef]/[hi];
r = [ef]-j*[hi];
l = [rg]/[hi];
if j > 0, result doesn't fit
x = [kl];
如果a
和b
有符号,请先固定符号,然后用绝对值进行计算,如@Serge所示:
如果a或b为零,x=(-1)/c
否则,
符号(x)=符号(a)*符号(b)*符号(c)
您可以重新安排您的计算:
x = (a*b - 1) / c
= a*b/c - 1 / c
= (a/c)*b - 1 / c ;If a is likely to be huge
= a*(b/c) - 1 / c ;If b is likely to be huge
问题是精度损失。通过跟踪值的范围和引入比例因子(选择使中间值尽可能大而不会溢出),可以将这一点降至最低
例如,如果a
可能从0到1024,b
可能从0到16777215,c
可能从4096到8192;那么:
x = (a * ((256*b) /c) - 256 / c) / 256
在这种情况下,
(256*b)将128位算术作为四个32位数字执行?这并不难。甚至汇编程序:MOV、MUL、long decreation、DIV
。它们(VC等)还没有int128
吗?浮点运算可能会引入一个错误。1.0/c
在我看来像是一个浮点运算。当我添加此代码时,编译器抱怨:错误C2415:操作数类型不正确,在两行中包含RAX。我认为VS不允许RAX。您是为64位目标构建此代码吗?@user1704182 even如果指定目标CPU?@user1704182请在Visual Studio中的配置管理器中检查生成目标;cf.那么您想以32位计算机为目标吗?那么我的代码将无法工作。我最初将其作为算法而不是实现编写。[ab]表示a*2^32+b(在base-2^32中串联)@ USE1704182请检查第一部分-我固定了一个“bug”@哔叽,我用“长”作为“两个32位字”,而不是“长”在C++感;-)JAN任何代码>长< /C> >移位32位,结果将产生0。在计算过程中,你会丢失进位。所以e,f,g必须是long
(或者VC中代表64位整数的任何类型)一个问题是r可能大到足以变成64位并且[rg]=[yzg]。在这种情况下,l=[yzg]/[hi]。我们回到原来的问题上来
x = (a*b - 1) / c
= a*b/c - 1 / c
= (a/c)*b - 1 / c ;If a is likely to be huge
= a*(b/c) - 1 / c ;If b is likely to be huge
x = (a * ((256*b) /c) - 256 / c) / 256