在C#和C++中将float/double乘以0.5而不是除以2是否安全?

Joa*_*nge 5 .net c# c++ optimization performance

基本上这样的事情(不是真正的代码):

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;
}
Run Code Online (Sandbox Code Playgroud)

v0.pos是类型Vector3<float, float, float>,但可能是Vector3<double, double, double>.

这样做是否安全?:

Vector3 center = (v0.pos + v1.pos) * 0.5;
Run Code Online (Sandbox Code Playgroud)

这似乎是过早的优化,但必须尽可能快地在数十亿点(点云)上调用.

Chr*_*ain 3

无论如何,我不是 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);
Run Code Online (Sandbox Code Playgroud)

生成 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));
Run Code Online (Sandbox Code Playgroud)

产生:

0.333333333333333
0.3333333
Run Code Online (Sandbox Code Playgroud)

所以,“安全”,也许,如果失去精确度 获得额外的精度是可以的。