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

时间:2012-01-16 18:27:54

标签: c# c++ .net performance optimization

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

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 个答案:

答案 0 :(得分: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);

生成前者的IL:

  1. 加载参数
  2. 添加它们(生成一个)
  3. 将结果转换为double
  4. 加载双参数(0.5)
  5. 相乘(产生双倍)
  6. 返回结果
  7. 和后者

    1. 加载参数
    2. 添加它们(生成一个)
    3. 加载常数整数(2)
    4. 除以(生成单个,因为单个/整数生成单个)
    5. 将结果转换为double
    6. 返回结果
    7. 令我感到震惊的是,前者可能具有更高的精度,因为乘法是在2个双精度上进行的,导致双精度,而在后者中,除法是在单个上进行上升到双精度(但仍然只会具有单一的精度。

      这让我失望:

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

      产生

      0.333333333333333
      0.3333333
      

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