Разница между "Math.DivRem" и% оператором?

В чем разница между System.Math.DivRem() и оператором %?

Ответы

Ответ 1

% дает вам остальную часть деления и полностью отбрасывает значение, а DivRem() вычисляет и возвращает как фактор, так и остаток.

Если вас беспокоит остальная часть деления между двумя целыми числами, используйте %:

int remainder = 10 % 3;
Console.WriteLine(remainder); // 1

Если вам нужно знать, сколько раз 10 было разделено на 3, прежде чем осталось 1, используйте DivRem(), который возвращает фактор и сохраняет остаток в выходном параметре:

int quotient, remainder;
quotient = Math.DivRem(10, 3, out remainder);
Console.WriteLine(quotient);  // 3
Console.WriteLine(remainder); // 1

Ответ 2

Это оптимизация. Некоторые процессоры могут одновременно вычислять оба значения. Другие процессоры не могут разделить аппаратное обеспечение (и должны использовать, очень медленно, программные подпрограммы).

В любом случае (если у вас нет интеллектуального компилятора) вы можете в конечном итоге вычислить одно и то же подразделение дважды. Поскольку деления никогда не бывают быстрыми, на любом процессоре (даже если они реализованы в аппаратном обеспечении), то использование Math.DivRem дает JIT хороший "подсказку" для вычисления значений только один раз.

iirc Моно не реализует эту оптимизацию, и я даже не уверен, что MS делает.

Ответ 3

Возможно, это была оптимизация, но, к сожалению, производит тот же IL-код, что и операция разделения PLUS.

В типичных архитектурах (x86 и друзьях) два могут быть получены из одной операции, но .NET JIT, похоже, не оптимизирует это (в моих тестах).

Итак, следующие два эквивалентны:

quotient = Math.DivRem(10, 3, out remainder);

VS:

quotient  = 10 / 3;
remainder = 10 % 3;

Кроме того, более поздняя версия более читаема.

Для записи эта уродливая опция выполняется быстрее на x86 и x64:

quotient  = 10 / 3;
remainder = 10 - (3*quotient);

Надеюсь, JIT улучшится в один прекрасный день, чтобы оптимизировать две операции в одну, поскольку это тривиально.