Умножает обратное лучше или хуже?

При работе с double типы данных умножаются на обратное лучше или хуже?

Каким образом быстрее? Какой способ использует меньше памяти? Какой способ является предпочтительным?

Как MSIL справляется с этим?

SquareInches = MMSquared / 645.16 
SquareInches = MMSquared * 0.0015500031000062000124000248000496

NB: 10K пользователи заметят, что это дубликат этого вопроса, который был удален, поскольку оригинал вопрос спрашивает, решил ли он все в разделе "комментарии" вопрос.

Этот вопрос был повторно отправлен, потому что это "хороший" вопрос.

Пожалуйста, снимите флажок "Community Wiki для вашего ответа, так как я публикую это только как CW, чтобы он не рассматривался как" репутация ".

Связанный с нами вопрос:

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

Ответ 1

Умножение на обратное происходит быстрее. Компиляторы не оптимизируют это автоматически, потому что это может привести к небольшой потере точности. (Это действительно появилось в группе новостей D Walter Bright часто, и он дал понять, что компиляторы не делают это автоматически.) Обычно вы должны делиться, потому что это более читаемо и точно.

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

Ответ 2

Какой из них " быстрее" действительно является проблемой, специфичной для процессора, или, по крайней мере, насколько быстрее процессор имеет специфическое значение, да, деление обычно рассматривается как медленнее, чем умножение. И, конечно, на все вопросы по производительности можно ответить "это зависит".

ОДНАКО, если бы вы спросили, что " лучше", а не быстрее, будет четкий ответ, более читаемый лучше. Улучшение производительности, на которое вы смотрите, скорее всего, порядка нескольких тактов, поэтому, если вы не говорите об этом миллионы раз, вы пытаетесь сэкономить микросекунды. И нет микросекундной оптимизации, которая стоит жертвует удобочитаемостью и ремонтопригодностью.

Ответ 3

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

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

SquareInches = MMSquared * (1 / 645.16)

И желательно использовать константу для 645.16.

Ответ 4

Ответ будет зависеть от архитектуры среды выполнения. В общем случае деления обычно немного дороже, чем умножение на большинстве процессоров.

Итак, , если это не является проблемой производительности, я, вероятно, не стал бы беспокоиться об этом. Выберите коэффициент конверсии, который станет более понятным.

Ответ 5

из моего таймера кода VB

Dim SquareInches As Double
Dim MMSquared As Double = 81
Const d As Double = 645.16
Const m As Double = 1 / 645.16
Private Function TestCase1() As Boolean 'One
    'Test One Code Here
    SquareInches = MMSquared / d
    'end test code
    Return True
End Function
Private Function TestCase2() As Boolean 'Two
    'Test Two Code Here
    SquareInches = MMSquared * m
    'end test code
    Return True
End Function

Результаты

     3/17/2009 2:13:27 PM   CPU - 1.794GHz
 One - Using Division
 Two - Using Multiplication
 Outer Loops(OL)=7  Inner Loops=262,144
  ( times in ticks.  1 ms. = 10,000 ticks )
 >> Two faster, 0.0488 ticks/loop
  Ticks / Loop
 0.0342         0.0819          0.0331          0.0488
 OL Base        One             Two              One - Two
 1   8,936          21,459          8,609           12,850
 2   9,008          21,416          8,682           12,734
 3   8,965          21,423          8,643           12,780
 4   8,964          21,457          8,659           12,798
 5   8,966          21,469          8,640           12,829
 6   8,987          21,660          8,688           12,972
 7   8,963          21,429          8,802           12,627

  Average
 8,969          21,473          8,674           12,799
  Variance
 431.4          6,160.3         3,315.9       
  Standard Deviation
 20.8           78.5            57.6          
 3/17/2009 2:13:27 PM

Ответ 6

Алгоритмы разделения медленнее, чем алгоритмы умножения в большинстве случаев.

Это компромисс, вы можете выбрать либо более читаемый способ, либо более быстрый способ.

// Using division operation
SquareInches = MMSquared / 645.16 

Это легко читать и поддерживать, но выполняет медленнее, чем его мультипликативный аналог:

// Using a multiplication 
SquareInches = MMSquared * 0.0015500031000062000124000248000496

Если вы пройдете этот путь, вам понадобится больше места в памяти для хранения чисел обратного числа, но алгоритм выполняется существенно медленнее. Пользователь протестировал его в проекте VS2005 и сообщил о производительности в 8 раз быстрее для мультипликативной версии.

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

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

Ответ 7

Что касается компиляторов, выполняющих оптимизацию для mult, они могут оптимизировать это (GCC): SquareInches = MMSquared * (1/645.16).

Ответ 8

Если вы делятся на буквенное значение, например 645.16, то очень вероятно, что нет никакой разницы, потому что компилятор может легко определить, какая версия работает быстрее и использовать. Если вы делите или умножаете на переменную, то, скорее всего, умножение будет немного быстрее, потому что логика, как правило, более простая.
Как и в любом случае, используйте профилировщик.

Ответ 9

Умножает и добавляет самые быстрые операции, поддерживаемые процессором. Некоторые процессоры даже не имеют аппаратных реализаций таких вещей, как деление, квадратный корень и т.д.

Ответ 10

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

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

Ответ 11

Я бы подумал, что первый метод явно предпочтительнее, потому что он явный. Представьте, что вы нашли это в коде другого. Как вы уверены, что 0.00155... действительно 1/645.16? Что, если оригинальный программист ошибся? Кроме того, откуда я узнаю, что 645.16 является правильным коэффициентом пересчета? Всегда просто не оставлять числа, уплотненные или представленные в форме для простоты. Самый простой пример:

//hours per day * days per year
int hoursPerYear = 24*365;

Мы можем ясно видеть, что это число правильно, но как бы вы знали, из-за того, что 8760 - правильный ответ? Если вам нужно выполнить многие из этих операций, вы можете предварительно обработать данные в правильной форме перед началом интенсивных вычислений. Таким образом, вам не понадобится невероятная эффективность, и вопрос станет спорным.