Неисправный код C # с использованием двойных и целых чисел - PullRequest
0 голосов
/ 05 апреля 2009
    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();
    }

Может ли кто-нибудь увидеть какие-либо непосредственные проблемы с этим кодом? Переменные tr и tb всегда оцениваются в 0.

Я рад предоставить дополнительную информацию, если она необходима.

Ответы [ 3 ]

1 голос
/ 05 апреля 2009

Вы не указали типы для других переменных - в частности, какие типы camera.fov_x и camera.fov_y? Если они оба целые, то строки, инициализирующие angx и angy, будут оцениваться с использованием целочисленной арифметики.

Это можно исправить, применив один из операндов:

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

Переменные fovy и fovx уже удваиваются, но это не проблема.

Не могли бы вы привести полный пример этого, который мы можем скомпилировать и протестировать сами?

РЕДАКТИРОВАТЬ: редактирование 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();
}
1 голос
/ 06 апреля 2009

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

Возможно, вы захотите использовать метод LockBits (), см. ответ и этот для получения более подробной информации. Другой способ - получить доступ к данным, используя «небезопасный» код C #, который позволяет использовать указатели на данные. См. этот вопрос для получения дополнительной информации, я получил ускорение ~ x2 с помощью "небезопасного" кода.

0 голосов
/ 05 апреля 2009

Не забудьте привести ваши целые числа к двойным. Например:

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
...