Wolfram mathematica Mathematica CForm/FortranForm bug?

Wolfram mathematica Mathematica CForm/FortranForm bug?,wolfram-mathematica,Wolfram Mathematica,我试图从Mathematica输出一个非常复杂的矩阵(纯文本约1.3MB),用于Fortran程序。当我这样做时(通过拼接),当给变量提供数值时,得到的矩阵会关闭约2%。这是一个问题,因为需要一个精确为零的特征值,并且特征向量的组成需要精确正确 我已经做了所有关于精度、正确变量、正确对角化代码等的尽职调查,结果要么是Fortran本身无法处理如此大的矩阵,要么是Mathematica弄乱了FortranForm的输出 所以我让Mathematica给我矩阵的CForm,并尝试了一下。它也比它应该

我试图从Mathematica输出一个非常复杂的矩阵(纯文本约1.3MB),用于Fortran程序。当我这样做时(通过
拼接
),当给变量提供数值时,得到的矩阵会关闭约2%。这是一个问题,因为需要一个精确为零的特征值,并且特征向量的组成需要精确正确

我已经做了所有关于精度、正确变量、正确对角化代码等的尽职调查,结果要么是Fortran本身无法处理如此大的矩阵,要么是Mathematica弄乱了FortranForm的输出

所以我让Mathematica给我矩阵的CForm,并尝试了一下。它也比它应该的值降低了约2%,更令人惊讶的是,它与FortranForm矩阵相同(在机器精度范围内)

有人接触过这种问题吗?你知道是什么引起的吗?我担心需要通过25000行Mathematica格式化的Fortran代码来解决这个问题

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


矩阵的(1,1)元素的,和。正常参数值为:0 这可能是以下简单的事情吗:Mathematica在数值计算方面非常聪明,例如这两个表达式

N[(10^18+100)-10^18]
N[10^18+100]-N[10^18]
产生完全不同的结果

Out[3]= 100.
Out[4]= 128. 
使用C或Fortran时,您不会得到任何保姆,表达式将按第二行计算。
也许你可以像C/Fortran那样在Mathematica中对单个矩阵条目求值,看看它是否与你所看到的相符

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

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

您能检查一下您的矩阵的编译版本是否符合C/Fortran吗?

查看第一个元素的表达式,这几乎肯定是一个问题,因为有有限精度浮点运算。在我看来,有两种方法可以尝试解决这个问题。首先是在C代码中使用更高的精度。也许您可以使用宏预处理器(或者只是查找和替换)将C代码中的所有声明从double更改为long double。取决于您使用的编译器,它将使您从64位变为80位或128位(除非您使用将长双精度视为标准双精度的编译器)。如果您发布了您正在使用的C编译器,我可以帮助您了解要实现这一目标需要做哪些更改。最后,如果需要将其传递给Mathematica或另一个仅使用double的C程序,则可以向下转换为double

此外,C编译器可以有不同的浮点模式。可能值得检查模式是否设置为精确、严格或快速。如果是关于快速或快速数学,那么这可能会导致你的取整问题

另一种方法是使用Mathematica重新排列每个元素的项,以优化浮点精度。在浮点运算领域,一般来说(a*b)*c=(c*b)*a是不正确的。我听说过的最好的启发是:

  • 添加:从最小值到最大值添加术语,以最大限度地减少舍入误差
  • 减法:避免或延迟相距非常近的值的减法,以便尽可能多地保留有效数字
  • 乘法/除法:避免/延迟乘以非常小的数字或除以非常大的数字,原因是再次出现有效数字

  • 实际上,这意味着分解这些表达式是最好的选择,尤其是有问题的术语。如果a1~=a2,那么表达式(a1-a2)(b-d)应该比(a1-a2)*b-(a1-a2)*d具有更高的精度/有效位数,因为您的乘法运算更少

    你能在更小的矩阵中重现错误吗?我是否正确地理解你导出的是符号矩阵?当你用Fortran/C计算它并将数值结果导入Mathematica时,与用Mathematica计算符号表达式相比,条目减少了2%。@HighPerformanceMark:不,我们用更简单的矩阵进行了测试,它们都在机器精度范围内复制。@Janus:Yep,这正是正在发生的事情。6x6矩阵1.3MB?数组[myGuinnessRecord[…:d我们矩阵的元素最多为O(10^6),单个变量为O(1)-O(1000)在单精度范围内,当然也在双精度范围内,这是我们在Fortran中使用的。此外,我们人为地将Mathematica的精度降低到了4位,但仍然得到了原始结果的0.01%以内。那么,N[expr,4]的误差小于10^-4正是框中所说的:如果我理解正确,N[,k]保证结果正确到k位精度。我可以肯定地想到,在某些情况下,即使工作精度更高,也会比N[,4]的精度低@Timo:在尝试了各种聪明的代码使Mathematica变得愚蠢之后,我意识到编译是测试中间精度是否是你的问题的简单方法。请参见上面的编辑。是的,Mathematica并不是如此愚蠢,我们只是想看看矩阵元素的低精度评估是否正确(我们尝试评估单个元素,尽管它们本身非常大)将重现Fortran和C产生的错误。由于Fortran和C产生的错误是相同的,与机器结构无关,也不能通过降低Mathematica的精度来重现,因此我们得出结论,剩下的唯一共同点是Mathematica产生了某种错误代码,但具有完全相同的e