【问题标题】:Faulty C# code involving doubles and integers涉及双精度和整数的错误 C# 代码
【发布时间】:2010-10-17 15:25:51
【问题描述】:
    for (iy = 0; iy < h; iy++)
    {
        double angy = (camera.fov_y / h) * iy;
        for (ix = 0; ix < w; ix++)
        {
            double angx = (camera.fov_x / w) * ix;
            //output[ix,iy].r = (int)Math.Round(255 * (angy / camera.fov_y);
            //output[ix,iy].b = (int)Math.Round(255 * (angy / camera.fov_y); 
            double tr = (angx / camera.fov_x) * 255D;
            double tb = (angy / camera.fov_y) * 255D;
            Console.Write("({0},{1})",Math.Round(tr),Math.Round(tb));

            output.SetPixel(ix, iy, Color.FromArgb(Convert.ToInt32(tr), 0, Convert.ToInt32(tb)) );
            Console.Write(".");
        }
        Console.WriteLine();
    }

任何人都可以看到该代码的任何直接问题吗? 变量 trtb 始终计算为 0。

如果需要,我很乐意提供更多信息。

【问题讨论】:

    标签: c# integer double


    【解决方案1】:

    您还没有给出其他变量的类型 - 特别是 camera.fov_xcamera.fov_y 的类型是什么?如果它们都是整数,那么初始化 angxangy 的行将使用整数运算进行计算。

    这可以通过强制转换操作数之一来解决:

    double angy = ((double) camera.fov_y / h) * iy;
    

    fovyfovx 变量已经是双精度数了,这不是问题。

    您能否给出一个完整的例子,我们可以自己编译和测试?

    编辑:Koistya Navin 的编辑太过分了。您只需要将表达式的一个操作数设为双精度,就可以使用双精度算术计算整个事物。 (不过,它必须是正确的表达式 - 如果您执行 (a/b) * c 并将 c 转换为双精度,则乘法将使用双精度运算完成,但 a/b 仍可能以整数形式完成。)

    这里的清单进行了适当的更改,以确保在应该使用的任何地方都使用双重算术:

    // Changed loops to declare the variable, for stylistic purposes
    for (int iy = 0; iy < h; iy++)
    {
        // Changed here - cast camera.fov_y
        double angy = ((double) camera.fov_y / h) * iy;
        for (int ix = 0; ix < w; ix++)
        {
            // Changed here - cast camera.fov_x
            double angx = ((double) camera.fov_x / w) * ix;
            //output[ix,iy].r = (int)Math.Round(255 * (angy / camera.fov_y);
            //output[ix,iy].b = (int)Math.Round(255 * (angy / camera.fov_y); 
            double tr = (angx / camera.fov_x) * 255D;
            double tb = (angy / camera.fov_y) * 255D;
            Console.Write("({0},{1})", Math.Round(tr), Math.Round(tb));
    
            output.SetPixel(ix, iy, Color.FromArgb(Convert.ToInt32(tr), 
                                                   0,
                                                   Convert.ToInt32(tb)) );
            Console.Write(".");
        }
        Console.WriteLine();
    }
    

    【讨论】:

    • 自发布以来我已经更改了几行,但这里是完整的源代码。 Program.cs - pastebin.com/f4c133638 Classes.cs - pastebin.com/d18b37a35 MiscFunctions.cs - pastebin.com/febb33ca
    • 顺便说一句,我知道整个代码对于它产生的东西来说是相当大的,但我的目标是制作一个光线追踪引擎,所以这就是 ang 位和 camera.fov位进来;)
    【解决方案2】:

    不要忘记将整数转换为双精度数。例如:

    for (iy = 0; iy < h; iy++)
    {
        double angy = ((double) camera.fov_y / h) * iy;
        for (ix = 0; ix < w; ix++)
        {
            double angx = ((double) camera.fov_x / (double) w) * (double) ix;
            output[ix,iy].r = (int) Math.Round(255 * (angy / camera.fov_y);
            output[ix,iy].b = (int) Math.Round(255 * (angy / camera.fov_y);
            double tr = (angx / camera.fov_x) * 255D;
            double tb = (angy / camera.fov_y) * 255D;
            Console.Write("({0},{1})",Math.Round(tr), Math.Round(tb));
            output.SetPixel(ix, iy, Color.FromArgb(
                Convert.ToInt32(tr), 0, Convert.ToInt32(tb)) );
            Console.Write(".");
        }
        Console.WriteLine();
    } 
    

    快速参考:

     int * double = double
     int / double = double
     double * int = double
     double / int = double
    
     int * int = int
     int / int = int // be carefull here!
    
     1 / 10 = 0 (not 0.1D)
     10 / 11 = 0 (not 1)
     1D / 10 = 0.1D
     1 / 10D = 0.1D
     1D / 10D = 0.1D
    

    【讨论】:

    • 虽然我怀疑问题出在整数算术上,但该行是一个不好的例子: angx 已经是双精度数,因此该行不是 IMO 的问题。 (另外 255D 是一种更紧凑的写法(双)255。)
    【解决方案3】:

    它知道这不是您原始问题的一部分,但使用 SetPixel(..) 效率不高,如果您打算在光线追踪引擎中使用它可能会出现问题。

    您可能想要使用 LockBits() 方法,请参阅此 answerthis one 了解更多详细信息。他们的另一种方法是使用“不安全”的 C# 代码访问数据,它允许您使用指向数据的指针。有关更多信息,请参阅 this question,我通过使用“不安全”代码获得了 ~x2 加速。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-03
      • 1970-01-01
      • 1970-01-01
      • 2019-07-13
      • 1970-01-01
      • 1970-01-01
      • 2013-01-11
      • 2020-03-03
      相关资源
      最近更新 更多