Я должен использовать умножение или разделение?

Для точного соответствия наиболее целесообразно использовать ==. Кроме того, это будет быстрее, чем grep(), и, очевидно, намного проще.

which(string == "apple")
# [1] 1
113
задан Edmundito 24 June 2009 в 22:34
поделиться

17 ответов

Python:

time python -c 'for i in xrange(int(1e8)): t=12341234234.234 / 2.0'
real    0m26.676s
user    0m25.154s
sys     0m0.076s

time python -c 'for i in xrange(int(1e8)): t=12341234234.234 * 0.5'
real    0m17.932s
user    0m16.481s
sys     0m0.048s

умножение на 33% быстрее

Lua:

time lua -e 'for i=1,1e8 do t=12341234234.234 / 2.0 end'
real    0m7.956s
user    0m7.332s
sys     0m0.032s

time lua -e 'for i=1,1e8 do t=12341234234.234 * 0.5 end'
real    0m7.997s
user    0m7.516s
sys     0m0.036s

=> никакая реальная разница

LuaJIT:

time luajit -O -e 'for i=1,1e8 do t=12341234234.234 / 2.0 end'
real    0m1.921s
user    0m1.668s
sys     0m0.004s

time luajit -O -e 'for i=1,1e8 do t=12341234234.234 * 0.5 end'
real    0m1.843s
user    0m1.676s
sys     0m0.000s

=> это только на 5% быстрее

заключения: в Python это быстрее для умножения, чем разделиться, но поскольку Вы становитесь ближе к ЦП с помощью более усовершенствованного VMs или МОНЕТ В ПЯТЬ ЦЕНТОВ, преимущество исчезает. Довольно возможно, что будущий Python VM сделал бы его не важным

74
ответ дан Javier 24 November 2019 в 02:39
поделиться

Ну, если мы предполагаем, что добавить/подотследить операция стоит 1, затем умножьте затраты 5 и разделите затраты приблизительно 20.

0
ответ дан matma 24 November 2019 в 02:39
поделиться

Я предложил бы умножение в целом, потому что Вы не должны тратить циклы, гарантирующие, что Ваш делитель не 0. Это не применяется, конечно, если Ваш делитель является константой.

1
ответ дан Steve 24 November 2019 в 02:39
поделиться

Я читал где-нибудь, что умножение более эффективно в C/C++; Никакая идея относительно интерпретируемых языков - различие не, вероятно, незначительна из-за всех других издержки.

, Если это не становится палкой проблемы с тем, что более удобно в сопровождении/читаемо - я ненавижу его, когда люди говорят мне это, но таким образом верный.

1
ответ дан Christopher Lightfoot 24 November 2019 в 02:39
поделиться

Опасайтесь "предполагать, что умножение обычно лучше, таким образом, я пытаюсь придерживаться этого, когда я кодирую",

В контексте этого конкретного вопроса, лучше здесь означает "быстрее". Который не очень полезен.

Взгляды о скорости могут быть серьезной ошибкой. Существуют глубокие ошибочные последствия в определенной алгебраической форме вычисления.

См. арифметика С плавающей точкой с анализом ошибок . См. Важные вопросы в Арифметике С плавающей точкой и Анализе ошибок .

, В то время как некоторые значения с плавающей точкой точны, большинство значений с плавающей точкой является приближением; они - некоторое идеальное значение плюс некоторая ошибка. Каждая операция относится к идеальному значению и ошибочному значению.

самые большие проблемы возникают из попытки управлять двумя почти-равными-количествами. Самые правые биты (биты ошибки) прибывают для доминирования над результатами.

>>> for i in range(7):
...     a=1/(10.0**i)
...     b=(1/10.0)**i
...     print i, a, b, a-b
... 
0 1.0 1.0 0.0
1 0.1 0.1 0.0
2 0.01 0.01 -1.73472347598e-18
3 0.001 0.001 -2.16840434497e-19
4 0.0001 0.0001 -1.35525271561e-20
5 1e-05 1e-05 -1.69406589451e-21
6 1e-06 1e-06 -4.23516473627e-22

В этом примере, Вы видите, что, поскольку значения становятся меньшими, различие почти между равными количествами создают ненулевые результаты, где корректный ответ является нулем.

2
ответ дан S.Lott 24 November 2019 в 02:39
поделиться

Это становится большим количеством вопроса, когда Вы программируете в блоке или возможно C. Я полагаю, что с наиболее современными языками, что оптимизация, такая как это делается для меня.

2
ответ дан Seamus 24 November 2019 в 02:39
поделиться

Подразделение с плавающей точкой является (обычно) особенно медленным, поэтому в то время как умножение с плавающей точкой является также относительно медленным, это, вероятно, быстрее, чем подразделение с плавающей точкой.

, Но я более склонен ответить, что "это действительно не имеет значения", если профилирование не показало, что подразделение является небольшим узким местом по сравнению с умножением. Я предполагаю, тем не менее, что выбор умножения по сравнению с подразделением не собирается оказывать большое влияние производительности в Вашем приложении.

2
ответ дан mipadi 24 November 2019 в 02:39
поделиться

Умножение обычно быстрее - конечно, никогда медленнее. Однако, если это не очень важная скорость, запишите, какой бы ни является самым ясным.

3
ответ дан Dan Hewett 24 November 2019 в 02:39
поделиться

Если Вы работаете с целыми числами или не типы, с плавающей точкой не забывают Ваших bitshifting операторов: < <>>

    int y = 10;
    y = y >> 1;
    Console.WriteLine("value halved: " + y);
    y = y << 1;
    Console.WriteLine("now value doubled: " + y);
4
ответ дан sbeskur 24 November 2019 в 02:39
поделиться

Сделайте то, в чем Вы нуждаетесь. Думайте о своем читателе сначала, не волнуйтесь о производительности, пока Вы не уверены, что у Вас есть проблема производительности.

Позволяют компилятору сделать производительность для Вас.

6
ответ дан buti-oxa 24 November 2019 в 02:39
поделиться

Запишите, какой бы ни более ясно состояния Ваше намерение.

После Ваших работ программы, выясните то, что является медленным, и сделайте это быстрее.

не делают этого наоборот.

7
ответ дан Jay Bazuzi 24 November 2019 в 02:39
поделиться

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

y = x * (1.0 / 2.0);

компилятор должен быть в состоянии сделать деление во время компиляции, таким образом, Вы получаете умножение во времени выполнения. Я ожидал бы, что точность совпадет с в y = x / 2.0 случай.

то, Где это может иметь БОЛЬШОЕ ЗНАЧЕНИЕ, находится во встроенных процессорах, где эмуляция с плавающей точкой требуется, чтобы вычислять арифметику с плавающей точкой.

24
ответ дан Jason S 24 November 2019 в 02:39
поделиться

Умножение быстрее, подразделение более точно. Вы потеряете некоторую точность, если Ваше число не будет питанием 2:

y = x / 3.0;
y = x * 0.333333;  // how many 3's should there be, and how will the compiler round?

, Даже если Вы позволяете компилятору выяснить инвертированную константу к идеальной точности, ответ может все еще отличаться.

x = 100.0;
x / 3.0 == x * (1.0/3.0)  // is false in the test I just performed

проблема скорости, вероятно, будет, только иметь значение в C/C++ или языках JIT, и даже тогда, только если операция находится в цикле в узком месте.

37
ответ дан Mark Ransom 24 November 2019 в 02:39
поделиться

Я думаю, что это добирается так nitpicky, что Вы были бы более обеспеченным выполнением, вообще делает код более читаемым. Если Вы не выполняете операции тысячи, если не миллионы, времен, я сомневаюсь, что любой будет когда-либо замечать различие.

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

47
ответ дан Thomas Owens 24 November 2019 в 02:39
поделиться

Я всегда узнавал, что умножение более эффективно.

2
ответ дан Toon Krijthe 24 November 2019 в 02:39
поделиться

Всегда используйте то, что является самым ясным. Что-либо еще, что Вы делаете, пытается перехитрить компилятор. Если компилятор будет вообще интеллектуален, он приложит все усилия для оптимизации результата, но ничто не может заставить следующего парня не ненавидеть Вас за Ваше дрянное bitshifting решение (я люблю побитовую обработку между прочим, это интересно. Но забава! = читаемый)

Преждевременная оптимизация является корнем всего зла. Всегда помните три правила оптимизации!

  1. не оптимизируют.
  2. , Если Вы - эксперт, см. правило № 1
  3. , Если Вы - эксперт и можете выровнять по ширине потребность, затем используйте следующую процедуру:

    • Код неоптимизированный
    • определяет, как быстро "Достаточно быстро" - Примечание, какое требование пользователя / история требует той метрики.
    • Запись тест скорости
    • Тест существующий код - Если это достаточно быстро, Вы сделаны.
    • Перекод это оптимизировало
    • Тестовый оптимизированный код. ЕСЛИ это не встречает метрику, выбрасывает его и сохраняет оригинал.
    • , Если это встречает тест, удержите исходный код как комментарии

кроме того, делая вещи как удаление внутренних циклов, когда они не требуются, или предпочитание связанного списка по массиву для вида вставки не оптимизация, просто программируя.

65
ответ дан Bill K 24 November 2019 в 02:39
поделиться

Просто собираюсь добавить кое-что для опции "другие языки".
C: Так как это просто академическое упражнение, которое на самом деле не имеет значения, я подумал, что внес бы что-то другое.

Я скомпилировал для сборки без оптимизации и посмотрел на результат.
. Код:

int main() {

    volatile int a;
    volatile int b;

    asm("## 5/2\n");
    a = 5;
    a = a / 2;

    asm("## 5*0.5");
    b = 5;
    b = b * 0.5;

    asm("## done");

    return a + b;

}

скомпилирован с gcc tdiv.c -O1 -o tdiv.s -S

делением на 2:

movl    $5, -4(%ebp)
movl    -4(%ebp), %eax
movl    %eax, %edx
shrl    $31, %edx
addl    %edx, %eax
sarl    %eax
movl    %eax, -4(%ebp)

и умножением на 0. 5:

movl    $5, -8(%ebp)
movl    -8(%ebp), %eax
pushl   %eax
fildl   (%esp)
leal    4(%esp), %esp
fmuls   LC0
fnstcw  -10(%ebp)
movzwl  -10(%ebp), %eax
orw $3072, %ax
movw    %ax, -12(%ebp)
fldcw   -12(%ebp)
fistpl  -16(%ebp)
fldcw   -10(%ebp)
movl    -16(%ebp), %eax
movl    %eax, -8(%ebp)

Однако, когда я изменил эти ints на doubles (что, вероятно, и сделал бы питон), я получил следующее:

деление:

flds    LC0
fstl    -8(%ebp)
fldl    -8(%ebp)
flds    LC1
fmul    %st, %st(1)
fxch    %st(1)
fstpl   -8(%ebp)
fxch    %st(1)

умножение:

fstpl   -16(%ebp)
fldl    -16(%ebp)
fmulp   %st, %st(1)
fstpl   -16(%ebp)

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

В качестве примечания можно заметить, что в моей программе main() возвращает a + b. Когда я убираю волатильное ключевое слово, вы никогда не догадаетесь, как выглядит ассемблер (исключая настройку программы):

## 5/2

## 5*0.5
## done

movl    $5, %eax
leave
ret

она делала и деление, и умножение, и сложение в одной команде! Очевидно, что вам не стоит беспокоиться об этом, если оптимизатор какой-то респектабельный.

Извините за слишком длинный ответ.

21
ответ дан 24 November 2019 в 02:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: