1

あるMulDiv

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

C#またはそれに相当するものですか?

または私はそれを実装する必要がありますか?

編集:PInvokingなし!!

4

4 に答える 4

5

この API 関数は、Windows の 16 ビット バージョンである Windows バージョン 3 にさかのぼります。かなり前に、私は十分な年齢ではありません。C コンパイラで 2 つの 16 ビット数値 (2 つの int) を乗算し、32 ビットの中間結果を取得し、16 ビット数値で除算して 16 ビットの結果を取得するのは少し困難でした。操作は非常に一般的で、たとえばフォント サイズを計算します。

Microsoft の大きな負担の 1 つは、いったん API 関数を公開すると、それがオペレーティング システムの必要な変更と著しく互換性がない場合を除き、永久に維持しなければならないことです。MulDiv() について大したことはありませんが、int引数は自動的に 32 ビットにブーストされ、関数はほぼ完全に不要になりました。しかし、Win3 用に書かれたプログラムは依然としてコンパイルされ、バック互換性は神聖です。

これで API に負担をかけるのは少し間違いでしたが、動機は強く、ウィンドウ システムを 640 キロバイトに詰め込むのはかなり困難でした。OS が必要とするために既に存在するものを公開することは、バイトを削減するのに非常に役立ちます。そのような他の api 関数は、wprintf()、lstrcpyXxx() などです。コア C ランタイム関数は現在でも使用でき、Unicode への切り替えによっても維持されます。Windows の考古学的記録。

それをピンボークする意味はありません.C#はこれを行うのに問題はありません:

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

オーバーフロー例外が必要な場合は、 checkedキーワードを使用します。

于 2012-06-12T20:42:59.000 に答える
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));
于 2012-06-12T19:29:56.780 に答える
0

2 つの 32 ビット整数が 32 ビット整数よりも大きい値を生成する可能性がある場合に対処するのに苦労していることを明確にしたい場合は、Math.BigMul を使用して、結果を除算するだけです。そしてそれを整数にキャストします。他の回答で述べられているように、.NET の 64 ビット整数のサポートは、以前は MulDiv が持っていたはずのすべての利点 (およびいくつかの利点) を提供しているようです。

int result = unchecked((int)(System.Math.BigMul(nNumber, nNumerator) / nDenominator));
于 2013-10-14T16:38:03.447 に答える