我在“ Ray Tracer挑战”中苦苦挣扎,在第4章中遇到了一个我无法超越的测试案例。
Scenario: Rotating a point around the x axis
Given p ? point(0, 1, 0)
And half_quarter ? rotation_x(? / 4)
And full_quarter ? rotation_x(? / 2)
Then half_quarter * p = point(0, ?2/2, ?2/2)
And full_quarter * p = point(0, 0, 1)
Run Code Online (Sandbox Code Playgroud)
第一个断言(half_quarter)可以正常工作,但是第二个断言(full_quarter)失败。
期望Matrix.Multiply(full_quarter,p)等于(0,0,1,1),但找到(0,6.12323399573677E-17,1,1)。'
我的实现rotation_x如下:
public static double[,] rotation_x(double radians)
{
var cos = Math.Cos(radians);
var sin = Math.Sin(radians);
return new[,]
{
{ 1, 0, 0, 0 },
{ 0, cos, -sin, 0 },
{ 0, sin, cos, 0 },
{ 0, 0, 0, 1 }
});
}
Run Code Online (Sandbox Code Playgroud)
这是我的乘法方法:
public static double[] Multiply(double[,] a, (double x, double y, double z, double w) b)
{
var product = new double[4];
for (var r = 0; r < 4; r++)
{
product[r] = a[r, 0] * b.x
+ a[r, 1] * b.y
+ a[r, 2] * b.z
+ a[r, 3] * b.w
;
}
return product;
}
Run Code Online (Sandbox Code Playgroud)
在前面的章节中,我有很多关于矩阵和向量乘法的测试案例,因此,我很确定该部分可以正常工作。但是还有什么可能是错的?
您正在传递?的某个值,但Math.PI不完全等于?。大约等于?到约17个有效数字之内。
正弦的正弦?正好为零。非常接近的正弦值?非常接近零。您得到的是:6 x 10 -17几乎接近零。
同样,π/ 2的余弦正好为零,但是您传入的π/ 2的值仅精确到17位,因此结果仅精确到17位。
类似地,Sqrt(2.0)/2.0不是精确地为2/2。近似值精确到约17个小数位。
系统中每个不是整数的数字都只能在17个小数位内正确,因此这里没有奥秘。您的结果正确到小数点后17位,因为您的输入正确到小数点后17位。您只能得到与输入一样多的精度。双精度不是无限精度!
(顺便说一下,很好地使用元组类型-但考虑使结构代表这些概念中的某些;这样,您可以将与这些概念相关联的方法放入结构中。)
| 归档时间: |
|
| 查看次数: |
148 次 |
| 最近记录: |