C 有 div 和 ldiv 。它们是否为商和余数生成单独的指令将取决于您特定的标准库实现以及编译器和优化设置。从 C99 开始,您还可以使用 lldiv 来表示更大的数字。
C has div and ldiv. Whether these generate separate instructions for the quotient and remainder will depend on your particular standard library implementation and compiler and optimization settings. Starting with C99, you also have lldiv for larger numbers.
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;
}
Python does.
>>> divmod(9, 4)
(2, 1)
Which is odd, because Python is such a high level language.
So does Ruby:
11.divmod(3) #=> [3, 2]
*** EDIT ***
It should be noted that the purpose of these operators is probably not to do the work as efficiently as possible, it is more likely the functions exist for correctness/portability reasons.
For those interested, I believe this is the code of the Python implementation for integer divmod:
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;
}
In Java (since 1.5) the class BigDecimal has the operation divideAndRemainder returning an array of 2 elements with the result and de remainder of the division.
BigDecimal bDecimal = ...
BigDecimal[] result = bDecimal.divideAndRemainder(new BigDecimal(60));
[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
[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
发布评论
评论(9)
C 有
div
和ldiv
。它们是否为商和余数生成单独的指令将取决于您特定的标准库实现以及编译器和优化设置。从 C99 开始,您还可以使用lldiv
来表示更大的数字。C has
div
andldiv
. Whether these generate separate instructions for the quotient and remainder will depend on your particular standard library implementation and compiler and optimization settings. Starting with C99, you also havelldiv
for larger numbers.Python 确实如此。
这很奇怪,因为 Python 是一种高级语言。
Ruby 也是如此:
*** 编辑***
应该注意的是,这些运算符的目的可能不是尽可能高效地完成工作,更可能的是这些函数的存在是出于正确性/可移植性的原因。
对于那些感兴趣的人,我相信这是代码整数
divmod
的 Python 实现:Python does.
Which is odd, because Python is such a high level language.
So does Ruby:
*** EDIT ***
It should be noted that the purpose of these operators is probably not to do the work as efficiently as possible, it is more likely the functions exist for correctness/portability reasons.
For those interested, I believe this is the code of the Python implementation for integer
divmod
:在 C#/.NET 中,您有
Math.DivRem
:http://msdn.microsoft.com/en-us/ library/system.math.divrem.aspx
但根据这个线程 这并不是一个优化。
In C#/.NET you've got
Math.DivRem
:http://msdn.microsoft.com/en-us/library/system.math.divrem.aspx
But according to this thread this isn't that much an optimization.
在 Java 中(自 1.5 起),类
BigDecimal
具有操作divideAndRemainder
,返回一个包含 2 个元素的数组,其中包含除法的结果和余数。Java 17 Javadoc: https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/math/BigDecimal.html#除法余数(java.math.BigDecimal)
In Java (since 1.5) the class
BigDecimal
has the operationdivideAndRemainder
returning an array of 2 elements with the result and de remainder of the division.Java 17 Javadoc: https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/math/BigDecimal.html#divideAndRemainder(java.math.BigDecimal)
Common Lisp 的做法是: http://www.lispworks.com/documentation/HyperSpec/Body /f_floorc.htm
Common Lisp does: http://www.lispworks.com/documentation/HyperSpec/Body/f_floorc.htm
.NET 框架具有
Math.DivRem
:虽然,
DivRem
只是这样的包装:(我不知道抖动是否可以/确实将此类事情优化为单个指令。)
The .NET framework has
Math.DivRem
:Although,
DivRem
is just a wrapper around something like this:(I have no idea whether or not the jitter can/does optimise that sort of thing into a single instruction.)
正如 Stringer Bell 提到的,
DivRem
未优化 最高 .NET 3.5。在 .NET 4.0 它使用 NGen。
我用
Math.DivRem
得到的结果 (debug;release = ~11000ms)我用
MyDivRem
得到的结果 (debug;release = ~11000ms)针对 x86 的项目。
Math.DivRem
使用示例方法签名
.NET 4.0 代码
.NET 4.0 IL
MSDN 参考
As Stringer Bell mentioned there is
DivRem
which is not optimized up to .NET 3.5.On .NET 4.0 it uses NGen.
The results I got with
Math.DivRem
(debug; release = ~11000ms)Results I got with
MyDivRem
(debug; release = ~11000ms)Project targeted for x86.
Math.DivRem
Usage exampleMethod signatures
.NET 4.0 Code
.NET 4.0 IL
MSDN Reference
Haskell具有 和 后者直接对应于机器指令(根据 Integral运营商引号与Div )
Divmod
可能不会。Haskell has both
divMod
andquotRem
that latter of which corresponds directly to the machine instruction (according to Integral operators quot vs. div) whiledivMod
may not.