2010-10-09 61 views
38

显然,x86(可能还有很多其他指令集)将分割操作的商和余数放在单独的寄存器中。现在同时划分并留下余地?

,我们或许可以信任的编译器优化代码,例如这样只用一个电话来划分:

(x/6) 
(x % 6) 

他们可能做的。尽管如此,还是可以使用语言(或库,但主要是寻找语言)支持同时提供除法和模数结果吗?如果是这样,它们是什么,语法是什么样的?

+1

您的代码段没有的东西,都不能以这种方式进行优化...... – 2010-10-09 00:05:43

+1

一个例子,我才意识到我错了代码段。更新它。 – Ben 2010-10-09 00:06:57

+2

来自每个人的巨大回复。吮吸,我只能选择一个作为“答案”,当他们中的许多是有效的答案。 – Ben 2010-10-12 01:13:41

回答

42

C有div and ldiv。这些是否为商和余数生成单独的指令将取决于您特定的标准库实现以及编译器和优化设置。从C99开始,对于更大的数字,您也有lldiv

+7

令人惊讶的是,为什么这是不被接受的答案 - 它完全符合要求。 – toriningen 2013-02-18 00:24:26

+0

有趣的是,单独使用mod并没有在4.8中用'div'实现:http://stackoverflow.com/questions/4361979/how-does-the-gcc-implementation-of-module-work-and-why-does -it-not-use-the – 2015-10-20 20:30:32

+0

超前并接受了这个答案。我知道这里还有很多有效的答案,所以很难说其中一个比其他人更“正确”,但C是谈论这些事情的好起点。 – Ben 2015-12-02 18:43:34

28

Python的确如此。

>>> divmod(9, 4) 
(2, 1) 

这很奇怪,因为Python是如此高级的语言。

所以确实红宝石:

11.divmod(3) #=> [3, 2] 

*编辑*

应当指出的是,这些经营者的目的可能不是尽可能高效地完成工作,它更有可能该功能存在正确性/便携性的原因。

对于那些有兴趣,我认为Python实现整数divmod的this is the code

static enum divmod_result 
i_divmod(register long x, register long y, 
    long *p_xdivy, long *p_xmody) 
{ 
long xdivy, xmody; 

if (y == 0) { 
    PyErr_SetString(PyExc_ZeroDivisionError, 
        "integer division or modulo by zero"); 
    return DIVMOD_ERROR; 
} 
/* (-sys.maxint-1)/-1 is the only overflow case. */ 
if (y == -1 && UNARY_NEG_WOULD_OVERFLOW(x)) 
    return DIVMOD_OVERFLOW; 
xdivy = x/y; 
/* xdiv*y can overflow on platforms where x/y gives floor(x/y) 
* for x and y with differing signs. (This is unusual 
* behaviour, and C99 prohibits it, but it's allowed by C89; 
* for an example of overflow, take x = LONG_MIN, y = 5 or x = 
* LONG_MAX, y = -5.) However, x - xdivy*y is always 
* representable as a long, since it lies strictly between 
* -abs(y) and abs(y). We add casts to avoid intermediate 
* overflow. 
*/ 
xmody = (long)(x - (unsigned long)xdivy * y); 
/* If the signs of x and y differ, and the remainder is non-0, 
* C89 doesn't define whether xdivy is now the floor or the 
* ceiling of the infinitely precise quotient. We want the floor, 
* and we have it iff the remainder's sign matches y's. 
*/ 
if (xmody && ((y^xmody) < 0) /* i.e. and signs differ */) { 
    xmody += y; 
    --xdivy; 
    assert(xmody && ((y^xmody) >= 0)); 
} 
*p_xdivy = xdivy; 
*p_xmody = xmody; 
return DIVMOD_OK; 
} 
+0

'divmod'只运行一个操作吗?这个函数的代码是什么? – BrunoLM 2010-10-09 00:08:10

+0

打败我吧。 divmod()是Python中的一个内置函数。 – 2010-10-09 00:08:36

+0

@BrunoLM我敢打赌大量的[插入喜欢的饮料]'divmod'只是单独执行两个操作并打包结果,但没有证据可供。 – 2010-10-09 00:09:37

2

的.NET框架有Math.DivRem

int mod, div = Math.DivRem(11, 3, out mod); 
// mod = 2, div = 3 

虽然DivRem只是周围像这样的包装:

int div = x/y; 
int mod = x % y; 

(我不知道是否将抖动/不优化这种东西为一条指令)

3

正如斯汀格贝尔提到的那里有DivRem其中is not optimized到.NET 3.5。

.NET 4.0 it uses NGen

Math.DivRem得到的结果(调试;松开=〜11000ms)

11863 
11820 
11881 
11859 
11854 

结果我MyDivRem得到(调试;松开=〜11000ms)

29177 
29214 
29472 
29277 
29196 

项目针对x86版本。


Math.DivRem使用例

int mod1; 
int div1 = Math.DivRem(4, 2, out mod1); 

方法签名

DivRem(Int32, Int32, Int32&) : Int32 
DivRem(Int64, Int64, Int64&) : Int64 

.NET 4.0代码

[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")] 
public static int DivRem(int a, int b, out int result) 
{ 
    result = a % b; 
    return (a/b); 
} 

.NET 4.0 IL

.custom instance void System.Runtime.TargetedPatchingOptOutAttribute::.ctor(string) = { string('Performance critical to inline across NGen image boundaries') } 
.maxstack 8 
L_0000: ldarg.2 
L_0001: ldarg.0 
L_0002: ldarg.1 
L_0003: rem 
L_0004: stind.i4 
L_0005: ldarg.0 
L_0006: ldarg.1 
L_0007: div 
L_0008: ret 

MSDN Reference

+3

这个答案有点让人误解,因为跳出你的时间似乎表明Math.DivRem在.Net 4.0中进行了优化,但是当你向旁边注意到时,它实际上并没有被优化。事实上,在我的测试中,在所有版本的.Net上,Math.DivRem()稍微比单纯的div和mod操作系统要慢。换句话说,它并没有得到优化。 – 2014-07-27 20:54:01

0
int result,rest; 
    _asm 
    { 
     xor edx, edx // pone edx a cero; edx = 0 
     mov eax, result// eax = 2AF0 
     mov ecx, radix // ecx = 4 
     div ecx 
     mov val, eax 
     mov rest, edx 
    } 
0

此返回结果的剩余日

 int result,rest; 
    _asm 
    { 
     xor edx, edx // pone edx a cero; edx = 0 
     mov eax, result// eax = 2AF0 
     mov ecx, radix // ecx = 4 
     div ecx 
     mov val, eax 
     mov rest, edx 
    } 
相关问题