Неисправный код на C #, содержащий двойные и целые числа
Вопрос
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.
Я рад предоставить дополнительную информацию, если это необходимо.
Решение
Вы не указали типы для других переменных - в частности, каковы типы camera.fov_x
и camera.fov_y
?Если они оба являются целыми числами, то строки, инициализирующие angx
и angy
будет вычисляться с использованием целочисленной арифметики.
Это может быть исправлено путем приведения одного из операндов:
double angy = ((double) camera.fov_y / h) * iy;
В fovy
и fovx
переменные уже удваиваются, хотя проблема не в этом.
Не могли бы вы привести полный пример этого, который мы можем скомпилировать и протестировать сами?
Редактировать:Правка Коистьи Навина - это перебор.Вам нужно, чтобы только один операнд выражения был двойным, чтобы все это было вычислено с использованием двойной арифметики.(Однако это должно быть правильное выражение - если вы это сделаете (a/b) * c
и бросил c
a double, умножение будет выполнено с помощью двойной арифметики, но 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();
}
Другие советы
Я знаю, что это не является частью вашего первоначального вопроса, но использование SetPixel (..) не очень эффективно и может стать проблемой, если вы планируете использовать его в механизме трассировки лучей.
Возможно, вы захотите использовать метод LockBits(), смотрите это ответ и этот для получения более подробной информации.Другой способ - получить доступ к данным с помощью "небезопасного" кода C #, который позволяет вам использовать указатели на данные.Видишь этот вопрос для получения дополнительной информации я получил ускорение ~ x2, используя "небезопасный" код.
Не забудьте преобразовать ваши целые числа в double.Например:
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