Безопасно ли умножать float / double на 0,5 вместо деления на 2 в C # и C ++? - PullRequest
5 голосов
/ 16 января 2012

В основном для таких вещей (не настоящий код):

for(int i = 0; i < 1000000000; ++i)
{
     Vert v0 = mesh.polygons[i].edges[0].vert0;
     Vert v1 = mesh.polygons[i].edges[0].vert1;

     Vector3 center = (v0.pos + v1.pos) / 2;
}

v0.pos имеет тип Vector3<float, float, float>, но может быть Vector3<double, double, double>.

Безопасно ли просто делать?:

Vector3 center = (v0.pos + v1.pos) * 0.5;

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

1 Ответ

3 голосов
/ 16 января 2012

Ни в коем случае не эксперт C ++, но в C #:

var a = new Func<float, float, double>((float f1, float f2) => (f1 + f2) * 0.5);
var b = new Func<float, float, double>((float f1, float f2) => (f1 + f2) / 2);

генерирует IL, который в первом:

  1. Загружает аргументы
  2. Добавляет их (производит единичное)
  3. Преобразует результат в двойной
  4. Загружает двойной аргумент (0,5)
  5. Умножает (производит двойное)
  6. Возвращает результат

и последний

  1. Загружает аргументы
  2. Добавляет их (производит один)
  3. Загружаетконстантное целое число (2)
  4. Делит (производит одиночное, потому что одиночное / целое число производит одиночное)
  5. Преобразует результат в двойное
  6. Возвращает результат

Меня поражает, что первый, скорее всего, будет иметь более высокую точность, потому что умножение выполняется на 2 двойных, что приводит к двойной точности, тогда как во втором деление выполняется на одиночном, который повышается до двойного (но все жетолько будет иметь точность одного).

Это меня утомляет:

Console.Out.WriteLine(((double)1) * ((double)1/3));
Console.Out.WriteLine((1) / ((float)3));

производит:

0.333333333333333
0.3333333

Итак, «безопасно», может быть, если теряет точность приобретает дополнительную точность в порядке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...