【发布时间】:2016-12-11 15:37:53
【问题描述】:
我的代码求解二次方程(在游戏逻辑刻度中)以解决任务 - 沿着空间中可移动物体的轨道找到卫星刻度偏移。
而且我在判别式(更远的D)计算中遇到了错误。我会提醒:D = b^2 - 4ac。
因为它是大物体的轨道,所以我的a,b & c 是这样的序数:
1E+8
1E+12
1E+16
据此,b^2 是关于1E+24 的订单数,而4ac 也是关于1E+24 的订单数。
但是这个方程根的数字要少得多,因为它们只是场景中的坐标。所以根大约是1E+3 ... 1E+4。
问题(已更新-具体化):因为浮点数(和双精度)b^2 和4ac 的值的浮动有不准确,这是足够小的(相对于这些非常大的数字 [测量的绝对不准确度大约有 1E+18]),但是因为 D == 它们之间的差异,所以当 D 是(从更大的值方面) 到上面提到的不准确的订单值是 (1E+18),它的值开始在 +1E+18 .. -1E+18 左右的范围内波动(即波动范围大于实际值的 [-100% .. +100%]!
显然,这种波动会导致错误的(甚至是错误的方向)刻度偏移。我的卫星开始摇晃(这很糟糕))。
注意:当我说“当D 接近零时”实际上D 离零还很远,所以我不能在这个值范围内将它分配给零。
我考虑过使用定点计算(这可以让我摆脱问题)。但是,不建议在滴答逻辑中使用(因为它们的优化程度要低得多,而且可能会很慢)。
我的问题:如何尝试解决我的问题?我的情况可能有一些常见的解决方案吗?非常感谢您的建议!
PS:所有公式都很好(当我的代码中的浮点数失败时,我在 excel 中计算了所有公式并得到了正确的结果)。
PPS:我尝试了双精度浮点数(不是所有计算,但我的 a、b 和 c 现在是双精度数)并且问题没有消失。
更新:我犯了一个错误-混淆了a、b和c的顺序。所以“b^2 是关于1E+16 的订单数,&4ac 是关于1E+28”是错误的。现在它都固定为1E+24。 (我已经写到这个已经写的cmets可以理解了)
更新#2:“问题”部分已具体化。
更新#3:值的真实案例(供参考): 注意:这里作为“准确值”,我将在 Excel 中手动计算的值标记出来。
a == 1.43963872E+8
b == 3.24884062357827E+12
c == 1.83291898112689E+16
//floats:
b^2 == 1.05549641E+25
4ac == 1.05549641E+25
D == 0.0
root:
y = -1.12835273E+4
//doubles:
b^2 == 1.0554965397412443E+25
4ac == 1.0554964543412880E+25
D == 8.5399956328598733E+17
roots:
y1 == -1.1280317962726038E+4
y2 == -1.1286737079932651E+4
//accurate values:
b^2 == 1.05549653974124E+25
4ac == 1.05549645434129E+25
D == 8.53999563285987E+17
roots:
y1 == -1.128031796E+4
y2 == -1.128673708E+4
双打看起来不错,但不是,因为这里我只给出了部分计算 - 这里我从相同的 a、b 和 c 值开始,但它们在我的代码中的实际值也被计算出来。并且包含不准确性,即使使用双打也会产生问题。
【问题讨论】:
-
如果您依赖准确性,则不应该使用
float。 -
您需要调整“接近零”的含义。在这里,您减去两个 1E28 量级的值,得到 1E18 量级的结果,相对误差仅为 1E-10。这是您应该检查的相对错误,而不是绝对错误。 (另外:您应该阅读处理此类问题的数值分析。)
-
定点并不神奇。你只是认为它会对你有所帮助,因为你没有尝试过。
-
"b^2 是大约 1E+16 的订单数" 不应该是 1E+24 的订单吗?
标签: c++ floating-point calculation