C#中有MulDiv吗?

时间:2012-06-12 19:28:35

标签: c#

MulDiv

WINBASEAPI
int
WINAPI
MulDiv(
    _In_ int nNumber,
    _In_ int nNumerator,
    _In_ int nDenominator
    );

在C#中还是等同于它?

还是我应该实施它?

编辑:没有PInvoking !!

4 个答案:

答案 0 :(得分:5)

这个api函数可以追溯到Windows版本3,一个16位版本的Windows。很可能之前,我还不够大。如果让C编译器将两个16位数字(两个整数)相乘有点困难,那么得到一个32位中间结果并除以一个16位数来得到一个16位结果。操作很常见,例如计算字体大小。

微软的一大负担是,一旦他们发布了api功能,他们必须永远保持 ,除非它与操作系统中的必要更改完全不兼容。没有什么关于MulDiv(), int 参数确实可以自动提升到32位,这使得函数完全没必要。但是为Win3编写的程序仍在编译,backcompat是神圣的。

用这个来加重api是一个错误,但动机很强,很难把窗口系统塞进640千字节。暴露已经存在的东西,因为操作系统需要它真的有助于削减字节。其他类似的api函数是wprintf(),lstrcpyXxx()等。核心C运行时函数和仍然现在可用,甚至通过切换到Unicode来维护。 Windows的考古记录。

没有必要对它进行排序,C#可以毫不费力地做到这一点:

public static int MulDiv(int number, int numerator, int denominator) {
    return (int)(((long)number * numerator) / denominator);
}

如果您想要溢出异常,请使用已检查关键字。

答案 1 :(得分:5)

这是对Hans Passant消化的增强,但包括根据MSDN docs的+0.5舍入:

public static int MulDiv(int number, int numerator, int denominator)
{
    return (int)(((long)number * numerator + (denominator >> 1)) / denominator);
}

注意:此代码使用右移运算符来获得最佳效果。

答案 2 :(得分:1)

不,这不是开箱即用的。您需要执行PInvoke

您当然可以自己实施:

//truncation is unnecessary if you want to continue using a long
//the truncation can never overflow so it is unchecked
var result = unchecked((int)(nNumber * (long)nNumerator / nDenominator));

答案 3 :(得分:0)

如果你想明确表示你想要处理两个32位整数可能产生大于32位整数的值的情况,你可以使用Math.BigMul,然后只是除以结果并将其转换回整数。我看到,正如其他答案所述,.NET对64位整数的支持显然提供了MulDiv以前所需的所有好处(然后是一些)。

int result = unchecked((int)(System.Math.BigMul(nNumber, nNumerator) / nDenominator));