2013-10-15 3 views
5

Мой профессор не любит использование modulo, так как он недостаточно эффективен, но я не уверен, как еще я могу получить тот же ответ, используя логический оператор или что-то в этом роде. Может кто-нибудь помочь мне, как я могу это сделать?Как удалить модуль из моей математической операции?

j = (j + 1) % a.length; 
+17

* sighs * у профессора –

+0

Вы можете сделать это с условным (если 'j' уже'

+4

Согласен.Проблемы профессора не являются обоснованными. За исключением специализированного приложения, modulo обычно быстрее, чем условный переход на многих языках, и даже если он медленнее, эта микрооптимизация по-прежнему на порядок медленнее, чем доступ к диску или сетевые задержки. – hexafraction

ответ

2

Вы можете сделать это:

j = j + 1; 
if (j >= a.length) { 
    j = j - a.length; // assumes j was less than length before increment 
} 

@ajp предлагает другое решение, которое на самом деле будет работать нормально.

j = j + 1; 
if (j >= a.length) { // assumes j was less than length before increment 
    j = 0; 
} 

Если бы я писал код, id напишите его так, на всякий случай. Она имеет очень мало дополнительные накладные расходы и снимает «предполагает»

j = j + 1; 
while (j >= a.length) { 
    j = j - a.length; 
} 

Конечно, % будет хороший способ сделать это тоже. Если только не твой профессор.

Это может быть быстрее или медленнее, чем разделить/по модулю в зависимости от стоимости перехода (и любого эффекта, который имеет на конвейер/график), и эффективности целых инструкций деления.

Старые процессоры, скорее всего, будут лучше с прыжком. Более современные с разрывом.

+0

Я предлагаю запустить некоторые тесты, когда у вас есть время, чтобы усилить ваш ответ. – hexafraction

+0

Примечание: если j было «меньше» длины до приращения, ваше условие всегда терпит неудачу. Вы можете означать, что «предполагает, что j было <= длина», или вы можете иметь в виду «if (j> = a.length)». – ajb

+0

@ajb Ты мертв. Это последнее. –

3

Это должно сделать трюк.

int k = a.length; 
int d = (j+1)/k; 
j = (j+1) - d*k 
+3

Проблема с этим решением заключается в том, что в большинстве систем/и% должны быть одной и той же операцией в любом случае, просто сохраняя другую часть результата, поэтому она фактически не изменяет скорость вообще. – qaphla

+3

Итак, если профессор ненавидит один по модулю, он или она будет действительно ненавидеть одно подразделение плюс одно умножение. –

+0

Предположительно, это будет медленнее, чем%? Не то чтобы это важно, все его нелепые микро оптимизации –

3

Единственный способ, которым я могу видеть, делать это без по модулю еще не велика:

j = (++j < a.length)? j : (j - a.length); 

С другой стороны, для получения дополнительной читаемости:

j++; 
j = (j < a.length)? j : (j - a.length); 

или

j++; 
if (j >= a.length) { 
    j -= a.length; 
} 

Кроме того, я не совсем уверен о том, как Java делает с предсказанием цикла, но по крайней мере на C, следующее будет немного лучше для скорости, если оно менее читаемо, поскольку общее предположение состоит в том, что аргумент для оператора if будет истинным, а j < a.length чаще, чем нет (Если a.length <= 2, который не кажется маловероятным.)

j++; 
if(j < a.length) { 
} 
else { 
    j -= a.length; 
} 

Если начальное значение j находится вне диапазона 0 до a.length (включительно эксклюзивные), то единственное решение либо использовать модуль или деление, которое, будучи таким же работающие, имеют одинаковую скорость или цикл вычитания, который будет по существу выполнять то же самое, что и модуль на очень старом процессоре, который медленнее, чем встроенная операция для модуля на любом текущем пр. о котором я знаю.

+0

Извините, пытаясь прочитать инструкцию, в которой вы используете предварительный приращение переменной, которую вы оба назначаете и используете в другом месте в том же самом выражении, дает мне головную боль. Даже если это сработает. Нет точек для перекоса всех в одну строку, если вы не программируете в APL. :) – ajb

+0

@ajb Я могу взять на себя вину за это, была моя идея. В то время это казалось хорошей идеей, но я вижу вашу точку зрения. – Cruncher

+0

Боюсь, что мне что-то не хватает, но что, если j огромно, как 1000000? и a.length мала, как 5 –

1

Подумайте, что вы здесь делаете. Вы, по сути, говорите:

if j + 1 is smaller than a.length, set j to j + 1 
otherwise, we set j to a value smaller than a.length 

Этот псевдокод должен дать вам очень четкий намек на решение.

+0

Что вы подразумеваете под «значением меньше, чем a.length» –

+1

@RichardTingle Я думаю, что он означает 'значение, которое меньше длины j, чем j, или какой-либо коэффициент длины меньше j, так что значение равно меньше чем a.length – Cruncher

Смежные вопросы