Ни в коем случае не эксперт 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, который в первом:
- Загружает аргументы
- Добавляет их (производит единичное)
- Преобразует результат в двойной
- Загружает двойной аргумент (0,5)
- Умножает (производит двойное)
- Возвращает результат
и последний
- Загружает аргументы
- Добавляет их (производит один)
- Загружаетконстантное целое число (2)
- Делит (производит одиночное, потому что одиночное / целое число производит одиночное)
- Преобразует результат в двойное
- Возвращает результат
Меня поражает, что первый, скорее всего, будет иметь более высокую точность, потому что умножение выполняется на 2 двойных, что приводит к двойной точности, тогда как во втором деление выполняется на одиночном, который повышается до двойного (но все жетолько будет иметь точность одного).
Это меня утомляет:
Console.Out.WriteLine(((double)1) * ((double)1/3));
Console.Out.WriteLine((1) / ((float)3));
производит:
0.333333333333333
0.3333333
Итак, «безопасно», может быть, если теряет точность приобретает дополнительную точность в порядке.