Defeituoso código C # envolvendo duplos e inteiros
Pergunta
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();
}
Alguém pode ver quaisquer problemas imediatos com esse código?
As variáveis ??tr
e tb
sempre avaliar a 0.
Estou feliz para fornecer mais informações se for necessário.
Solução
Você não deram os tipos para as outras variáveis ??- em particular, quais são os tipos de camera.fov_x
e camera.fov_y
? Se eles são ambos inteiros, em seguida, as linhas de inicialização angx
e angy
serão avaliados usando aritmética inteira.
Isso pode ser corrigido por vazamento de um dos operandos:
double angy = ((double) camera.fov_y / h) * iy;
As variáveis ??fovy
e fovx
já são duplos, porém, este não é o problema.
Você poderia dar um exemplo completo desta, que pode compilar e testar a nós mesmos?
EDIT: editar de Koistya Navin é um exagero. Você só precisa de um operando de uma expressão a ser um casal para toda a coisa a ser calculado usando dupla aritmética. (Ela precisa ser a expressão correta embora -. Se você fizer (a/b) * c
e c
elenco uma dupla, a multiplicação será feito com dupla aritmética, mas a / b ainda pode ser feito como inteiros)
Aqui está o anúncio mudou de forma adequada para se certificar de dupla aritmética é usado em todos os lugares que deve ser:
// 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();
}
Outras dicas
Ele sabe que não é parte da sua pergunta original, mas usando SetPixel (..) não é muito eficiente e pode ser um problema se você está planejando usá-lo em um motor de ray-tracing.
Você pode querer usar as LockBits () método, consulte este resposta e esta para mais detalhes. Eles outra maneira de ir é para acessar os dados usando o código "inseguro" C #, que permite usos ponteiros para os dados. Consulte esta questão para mais informações, eu tenho um ~ velocidade-up usando x2 " código inseguro".
Não se esqueça de lançar seus inteiros para duplos. Por exemplo:
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();
}
Referência rápida:
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