Mathematica CForm / FortranForm错误?

时间:2010-11-18 07:08:43

标签: wolfram-mathematica

我试图从Mathematica输出一个非常复杂的矩阵(纯文本大约1.3MB),以便在Fortran程序中使用。当我这样做时(通过Splice),当给变量赋值时,得到的矩阵偏差约2%。这是一个问题,因为需要一个恰好为零的特征值,并且特征向量的组成需要完全正确。

我已经完成了关于精度,正确变量,正确的对角化代码等的所有常规尽职调查。它归结为Fortran本身无法应对如此大的矩阵或Mathematica搞乱FortranForm输出。 / p>

所以我让Mathematica给我矩阵的CForm并尝试了。与它应该的相比还有2%的折扣,更令人惊讶的是,它与FortranForm矩阵相同(在机器精度范围内)!

有没有人接触过这类问题?你知道可能导致什么吗?我担心需要通过25000行Mathematica格式的Fortran代码来解决这个问题。

编辑:有问题的矩阵很复杂,并不大。它只有6x6,但每个元素都是单独的代数非常混乱,包括三角函数,对数和各种根和幂。

矩阵的(1,1)元素的PlaintextC codeFortran code。 Sane参数值为:0< lambda,kappa,Y ***< 1;所有其他人在100到1000之间。

2 个答案:

答案 0 :(得分:1)

可能是以下简单的事情:Mathematica对数值评估非常聪明,所以例如这两个表达式

N[(10^18+100)-10^18]
N[10^18+100]-N[10^18]

产生完全不同的输出

Out[3]= 100.
Out[4]= 128. 

使用C或Fortran,您不会进行任何保姆,表达式将按照第二行进行评估 也许您可以查看单个矩阵条目并尝试在Mathematica中将其作为C / Fortran评估,并查看它是否与您看到的匹配?

编辑:
似乎对中间精度问题的简单测试是使用Compile来删除所有精度检查,以便

In[10]:= Compile[{a,b},a+100-b][10^18,10^18]
Out[10]= 128.

你能检查矩阵的编译版本是否与C / Fortran一致吗?

答案 1 :(得分:1)

查看第一个元素的表达式,由于有限精度浮点运算,这几乎可以肯定是一个问题。在我看来,有两种方法可以尝试解决这个问题。第一种是在C代码中使用更高的精度。也许您可以使用宏预处理器(或只是查找和替换)将C代码中的所有声明从double更改为long double。根据您使用的编译器,它将使您从64位到80或128(除非您使用Microsoft's compiler将长双作为标准双精度)。如果你发布了你正在使用的C编译器,我可以帮助你看看你需要做出哪些改变才能走这条路线。如果您需要将其传递给Mathematica或其他仅使用双打的C程序,最后可以转换为double。

此外,C编译器可以有不同的浮点模式。可能值得检查模式是否设置为精确,严格或快速。如果它是快速或快速数学,则可能导致您的舍入问题。

另一种方法是使用Mathematica重新排列每个元素的术语,以优化浮点精度。虽然通常(a * b)* c =(c * b)* a在浮点运算的范围内,但这不是真的。我听说过的最好的启发式是:

  1. 添加:将条件从最小值添加到最大值以最小化舍入误差
  2. 减法:避免或延迟减去值中彼此非常接近的值,以便保持尽可能多的有效数字
  3. 乘法/除法:由于有效位数的原因,避免/延迟乘以非常小的数字或除以非常大的数字。
  4. 实际上,这意味着将这些表达式分解是最好的选择,尤其是有问题的术语。如果a1~ = a2那么表达式(a1-a2)(b-d)应该具有比(a1-a2)* b-(a1-a2)* d更精确/有效的数字,因为你有一个较少的乘法运算。