Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 方程中的多重/除法困境_C++_C - Fatal编程技术网

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)

我需要用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)
所以,如果你发现像

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