有MulDiv
WINBASEAPI
int
WINAPI
MulDiv(
_In_ int nNumber,
_In_ int nNumerator,
_In_ int nDenominator
);
在C#中还是等同于它?
还是我应该实施它?
编辑:没有PInvoking !!
答案 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));