我有一个相当长的表达式(https://pastebin.com/jUsxdCCs),它是 Maple 以符号方式生成的一组微分方程的解析解。我需要在 32 位系统中用 C 语言求解一组这样的方程。
长表达式有一个变量omega2,当被替换时会得到一个我感兴趣的数字。当这个操作在 Maple 中执行时,它会产生一个相当不错的浮点数,但是当我尝试在 C 中执行它时,(尝试使用omega2 = 100),我得到nan了,原因是长表达式中的某些子表达式超出了double2.3E-308 到 1.7E+308 的范围。我已经能够使用某些系统上可用的“long double”数据类型来解决这个问题,但这不是独立于平台的,并且绝对不能在我计划针对的具有 32 位 ARM 内核的微控制器上使用。
我可以想象的一种解决方案是使用 GMP 库,它可以处理无限精度的数字。只是想知道是否有任何其他 hack,因为 GMP'ing 整个代码可能相当麻烦,而且我没有足够的内存用于目标机器上的 GMP。
表达方式:
0.137197706359762e-3 * (-0.708981540362208e2 * cosh(0.354490770181104e2 * sqrt(omega2)) * sin(0.354490770181104e2 * sqrt(omega2)) * (-0.727331795502673e6 * cosh(0.354490770181104e2 * sqrt(omega2)) * sin(0.354490770181104e2 * sqrt(omega2)) - 0.209935630488671e8 * cosh(0.354490770181104e2 * sqrt(omega2)) * cos(0.354490770181104e2 * sqrt(omega2)) * sqrt(omega2) - 0.727331795502673e6 * cos(0.354490770181104e2 * sqrt(omega2)) * sinh(0.354490770181104e2 * sqrt(omega2))) * sqrt(omega2) / (0.348294222590750e3 * cosh(0.354490770181104e2 * sqrt(omega2)) * sinh(0.354490770181104e2 * sqrt(omega2)) * pow(sin(0.354490770181104e2 * sqrt(omega2)), 0.2e1) * sqrt(omega2) - 0.348294222590750e3 * cos(0.354490770181104e2 * sqrt(omega2)) * pow(sinh(0.354490770181104e2 * sqrt(omega2)), 0.2e1) * sin(0.354490770181104e2 * sqrt(omega2)) * sqrt(omega2) + 0.348294222590750e3 * pow(cosh(0.354490770181104e2 * sqrt(omega2)), 0.2e1) * cos(0.354490770181104e2 * sqrt(omega2)) * sin(0.354490770181104e2 * sqrt(omega2)) * sqrt(omega2) + 0.348294222590750e3 * cosh(0.354490770181104e2 * sqrt(omega2)) * pow(cos(0.354490770181104e2 * sqrt(omega2)), 0.2e1) * sinh(0.354490770181104e2 * sqrt(omega2)) * sqrt(omega2) + 0.120668159897616e2 * pow(cosh(0.354490770181104e2 * sqrt(omega2)), 0.2e1) * pow(sin(0.354490770181104e2 * sqrt(omega2)), 0.2e1) + 0.120668159897616e2 * pow(cos(0.354490770181104e2 * sqrt(omega2)), 0.2e1) * pow(sinh(0.354490770181104e2 * sqrt(omega2)), 0.2e1) + 0.502654824574368e4 * pow(sinh(0.354490770181104e2 * sqrt(omega2)), 0.2e1) * pow(sin(0.354490770181104e2 * sqrt(omega2)), 0.2e1) * omega2 + 0.502654824574368e4 * pow(cosh(0.354490770181104e2 * sqrt(omega2)), 0.2e1) * pow(cos(0.354490770181104e2 * sqrt(omega2)), 0.2e1) * omega2) - 0.708981540362208e2 * cosh(0.354490770181104e2 * sqrt(omega2)) * sin(0.354490770181104e2 * sqrt(omega2)) / (0.348294222590750e3 * cosh(0.354490770181104e2 * sqrt(omega2)) * sinh(0.354490770181104e2 * sqrt(omega2)) * pow(sin(0.354490770181104e2 * sqrt(omega2)), 0.2e1) * sqrt(omega2) - 0.348294222590750e3 * cos(0.354490770181104e2 * sqrt(omega2)) * pow(sinh(0.354490770181104e2 * sqrt(omega2)), 0.2e1) * sin(0.354490770181104e2 * sqrt(omega2)) * sqrt(omega2) + 0.348294222590750e3 * pow(cosh(0.354490770181104e2 * sqrt(omega2)), 0.2e1) * cos(0.354490770181104e2 * sqrt(omega2)) * sin(0.354490770181104e2 * sqrt(omega2)) * sqrt(omega2) + 0.348294222590750e3 * cosh(0.354490770181104e2 * sqrt(omega2)) * pow(cos(0.354490770181104e2 * sqrt(omega2)), 0.2e1) * sinh(0.354490770181104e2 * sqrt(omega2)) * sqrt(omega2) + 0.120668159897616e2 * pow(cosh(0.354490770181104e2 * sqrt(omega2)), 0.2e1) * pow(sin(0.354490770181104e2 * sqrt(omega2)), 0.2e1) + 0.120668159897616e2 * pow(cos(0.354490770181104e2 * sqrt(omega2)), 0.2e1) * pow(sinh(0.354490770181104e2 * sqrt(omega2)), 0.2e1) + 0.502654824574368e4 * pow(sinh(0.354490770181104e2 * sqrt(omega2)), 0.2e1) * pow(sin(0.354490770181104e2 * sqrt(omega2)), 0.2e1) * omega2 + 0.502654824574368e4 * pow(cosh(0.354490770181104e2 * sqrt(omega2)), 0.2e1) * pow(cos(0.354490770181104e2 * sqrt(omega2)), 0.2e1) * omega2) * sqrt(omega2) * (-0.209935630488671e8 * sinh(0.354490770181104e2 * sqrt(omega2)) * sin(0.354490770181104e2 * sqrt(omega2)) * sqrt(omega2) - 0.727331795502673e6 * cosh(0.354490770181104e2 * sqrt(omega2)) * sin(0.354490770181104e2 * sqrt(omega2)) + 0.727331795502673e6 * cos(0.354490770181104e2 * sqrt(omega2)) * sinh(0.354490770181104e2 * sqrt(omega2))) - 0.708981540362208e2 * cos(0.354490770181104e2 * sqrt(omega2)) * sinh(0.354490770181104e2 * sqrt(omega2)) * (-0.727331795502673e6 * cosh(0.354490770181104e2 * sqrt(omega2)) * sin(0.354490770181104e2 * sqrt(omega2)) - 0.209935630488671e8 * cosh(0.354490770181104e2 * sqrt(omega2)) * cos(0.354490770181104e2 * sqrt(omega2)) * sqrt(omega2) - 0.727331795502673e6 * cos(0.354490770181104e2 * sqrt(omega2)) * sinh(0.354490770181104e2 * sqrt(omega2))) * sqrt(omega2) / (0.348294222590750e3 * cosh(0.354490770181104e2 * sqrt(omega2)) * sinh(0.354490770181104e2 * sqrt(omega2)) * pow(sin(0.354490770181104e2 * sqrt(omega2)), 0.2e1) * sqrt(omega2) - 0.348294222590750e3 * cos(0.354490770181104e2 * sqrt(omega2)) * pow(sinh(0.354490770181104e2 * sqrt(omega2)), 0.2e1) * sin(0.354490770181104e2 * sqrt(omega2)) * sqrt(omega2) + 0.348294222590750e3 * pow(cosh(0.354490770181104e2 * sqrt(omega2)), 0.2e1) * cos(0.354490770181104e2 * sqrt(omega2)) * sin(0.354490770181104e2 * sqrt(omega2)) * sqrt(omega2) + 0.348294222590750e3 * cosh(0.354490770181104e2 * sqrt(omega2)) * pow(cos(0.354490770181104e2 * sqrt(omega2)), 0.2e1) * sinh(0.354490770181104e2 * sqrt(omega2)) * sqrt(omega2) + 0.120668159897616e2 * pow(cosh(0.354490770181104e2 * sqrt(omega2)), 0.2e1) * pow(sin(0.354490770181104e2 * sqrt(omega2)), 0.2e1) + 0.120668159897616e2 * pow(cos(0.354490770181104e2 * sqrt(omega2)), 0.2e1) * pow(sinh(0.354490770181104e2 * sqrt(omega2)), 0.2e1) + 0.502654824574368e4 * pow(sinh(0.354490770181104e2 * sqrt(omega2)), 0.2e1) * pow(sin(0.354490770181104e2 * sqrt(omega2)), 0.2e1) * omega2 + 0.502654824574368e4 * pow(cosh(0.354490770181104e2 * sqrt(omega2)), 0.2e1) * pow(cos(0.354490770181104e2 * sqrt(omega2)), 0.2e1) * omega2) + 0.708981540362208e2 * cos(0.354490770181104e2 * sqrt(omega2)) * sinh(0.354490770181104e2 * sqrt(omega2)) / (0.348294222590750e3 * cosh(0.354490770181104e2 * sqrt(omega2)) * sinh(0.354490770181104e2 * sqrt(omega2)) * pow(sin(0.354490770181104e2 * sqrt(omega2)), 0.2e1) * sqrt(omega2) - 0.348294222590750e3 * cos(0.354490770181104e2 * sqrt(omega2)) * pow(sinh(0.354490770181104e2 * sqrt(omega2)), 0.2e1) * sin(0.354490770181104e2 * sqrt(omega2)) * sqrt(omega2) + 0.348294222590750e3 * pow(cosh(0.354490770181104e2 * sqrt(omega2)), 0.2e1) * cos(0.354490770181104e2 * sqrt(omega2)) * sin(0.354490770181104e2 * sqrt(omega2)) * sqrt(omega2) + 0.348294222590750e3 * cosh(0.354490770181104e2 * sqrt(omega2)) * pow(cos(0.354490770181104e2 * sqrt(omega2)), 0.2e1) * sinh(0.354490770181104e2 * sqrt(omega2)) * sqrt(omega2) + 0.120668159897616e2 * pow(cosh(0.354490770181104e2 * sqrt(omega2)), 0.2e1) * pow(sin(0.354490770181104e2 * sqrt(omega2)), 0.2e1) + 0.120668159897616e2 * pow(cos(0.354490770181104e2 * sqrt(omega2)), 0.2e1) * pow(sinh(0.354490770181104e2 * sqrt(omega2)), 0.2e1) + 0.502654824574368e4 * pow(sinh(0.354490770181104e2 * sqrt(omega2)), 0.2e1) * pow(sin(0.354490770181104e2 * sqrt(omega2)), 0.2e1) * omega2 + 0.502654824574368e4 * pow(cosh(0.354490770181104e2 * sqrt(omega2)), 0.2e1) * pow(cos(0.354490770181104e2 * sqrt(omega2)), 0.2e1) * omega2) * sqrt(omega2) * (-0.209935630488671e8 * sinh(0.354490770181104e2 * sqrt(omega2)) * sin(0.354490770181104e2 * sqrt(omega2)) * sqrt(omega2) - 0.727331795502673e6 * cosh(0.354490770181104e2 * sqrt(omega2)) * sin(0.354490770181104e2 * sqrt(omega2)) + 0.727331795502673e6 * cos(0.354490770181104e2 * sqrt(omega2)) * sinh(0.354490770181104e2 * sqrt(omega2)))) * pow(omega2, -0.1e1 / 0.2e1) - 0.833338826540431e3;
简化 Maple 中的表达式,得到:
.414741582884880e315/(.702517310158453e311*pow(.487478610966388,2.)+.702517310158453e311*pow(-.873134928776922,2.)+502666.891390358*pow(.449112744897583e154,2.)*pow(.487478610966388,2.)+502666.891390358*pow(-.873134928776922,2.)*pow(.449112744897583e154,2.))*pow(.1e3,-.500000000000000)-833.338826540431
可以看出,sinh 和 cosh 项在内部爆炸,但最终抵消了。