matrix - 如果十进制更长,Fortran-逆矩阵结果不同
问题描述
我的真实数据是第一次输入,但结果的倒数太大了。当您与第一个和第二个输入进行比较时,它们是相同的数据。只有十进制大小不同。为什么会有不同的结果?因为它们是相同的数据。他们怎么会有不同的结果?您可以看到结果和输入。太奇怪了。
program test
Implicit none
double precision,allocatable,dimension(:,:) :: A
double precision,allocatable,dimension(:) :: WORK
integer ,allocatable,dimension(:) :: ipiv
integer :: n,info,M
external DGETRF,DGETRI
M=8
allocate(A(M,M),WORK(M),IPIV(M))
!!! First Input !!!!
A(1,:)=(/3.740486048842566D-4, 0.0D0, 0.0D0, 4.987315029057229D-5, 0.0D0, 0.0D0, 0.0D0, 0.0D0/)
A(2,:)=(/0.0D0 , 3.740486048842566D-4, 0.0D0, 0.0D0, 4.987315029057229D-5 ,0.0D0 ,0.0D0 ,0.0D0 /)
A(3,:)=(/0.0D0 , 0.0D0 ,3.740486048842566D-4, 0.0D0 ,0.0D0, 4.987315029057229D-5, 0.0D0 ,0.0D0/)
A(4,:)=(/4.987315029057229D-5 ,0.0D0 ,0.0D0 ,6.649753768432517D-6, 0.0D0 ,0.0D0, 0.0D0, 0.0D0 /)
A(5,:)=(/0.0D0 , 4.987315029057229D-5, 0.0D0, 0.0D0 ,6.649753768432517D-6 ,0.0D0 ,0.0D0 ,0.0D0 /)
A(6,:)=(/0.0D0, 0.0D0, 4.987315029057229D-5, 0.0D0 ,0.0D0, 6.649753768432517D-6, 0.0D0 ,0.0D0 /)
A(7,:)=(/0.0D0, 0.0D0 ,0.0D0, 0.0D0 ,0.0D0 ,0.0D0 ,1.499999910593033D-11, 0.0D0 /)
A(8,:)=(/0.0D0 ,0.0D0 ,0.0D0 ,0.0D0 ,0.0D0 ,0.0D0, 0.0D0 ,1.499999910593033D-11 /)
!!!! Second Input !!!!
!A(1,:)=(/3.74D-4, 0.0D0, 0.0D0, 4.98D-5, 0.0D0, 0.0D0, 0.0D0, 0.0D0/)
!A(2,:)=(/0.0D0 , 3.74D-4, 0.0D0, 0.0D0, 4.98D-5 ,0.0D0 ,0.0D0 ,0.0D0 /)
!A(3,:)=(/0.0D0 , 0.0D0 ,3.74D-4, 0.0D0 ,0.0D0, 4.98D-5, 0.0D0 ,0.0D0/)
!A(4,:)=(/4.98D-5 ,0.0D0 ,0.0D0 ,6.64D-6, 0.0D0 ,0.0D0, 0.0D0, 0.0D0 /)
!A(5,:)=(/0.0D0 , 4.98D-5, 0.0D0, 0.0D0 ,6.64D-6 ,0.0D0 ,0.0D0 ,0.0D0 /)
!A(6,:)=(/0.0D0, 0.0D0, 4.98D-5, 0.0D0 ,0.0D0, 6.64D-6, 0.0D0 ,0.0D0 /)
!A(7,:)=(/0.0D0, 0.0D0 ,0.0D0, 0.0D0 ,0.0D0 ,0.0D0 ,1.49D-11, 0.0D0 /)
!A(8,:)=(/0.0D0 ,0.0D0 ,0.0D0 ,0.0D0 ,0.0D0 ,0.0D0, 0.0D0 ,1.49D-11 /)
call DGETRF(M,M,A,M,IPIV,info)
if(info .eq. 0) then
Print *,'succeded'
else
Print *,'failed'
end if
call DGETRI(M,A,M,IPIV,WORK,M,info)
if(info .eq. 0) then
Print *,'succeded'
else
Print *,'failed'
end if
Print *,A
deallocate(A,IPIV,WORK)
end
!!!!! Second Input Result
!1.0e+10 *
! 0.0002 0 0 -0.0015 0 0 0 0
! 0 0.0002 0 0 -0.0015 0 0 0
! 0 0 0.0002 0 0 -0.0015 0 0
! -0.0015 0 0 0.0113 0 0 0 0
! 0 -0.0015 0 0 0.0113 0 0 0
! 0 0 -0.0015 0 0 0.0113 0 0
! 0 0 0 0 0 0 6.7114 0
! 0 0 0 0 0 0 0 6.7114
!!! First Input Result
! 1.0e+21 *
!-0.0238 0 0 0.1783 0 0 0 0
! 0 -0.0238 0 0 0.1783 0 0 0
! 0 0 0.0000 0 0 -0.0000 0 0
! 0.1783 0 0 -1.3375 0 0 0 0
! 0 0.1783 0 0 -1.3375 0 0 0
! 0 0 -0.0000 0 0 0.0000 0 0
! 0 0 0 0 0 0 0.0000 0
! 0 0 0 0 0 0 0 0.0000
解决方案
创建矩阵逆不是一个难题。我将您之前的示例转换为使用一种简单的方法,该方法基于带有阴影单位矩阵的高斯消元法,适用于大多数情况。附加的程序会反转您之前的对称矩阵,而不需要对行进行旋转。它不需要“黑匣子”。
用不同的系数得到不同的结果并不奇怪。由于输入值的明显微小变化导致结果显着变化,显示您正在使用的方程关系的灵敏度和可能较差的条件。
https://www.dropbox.com/s/ssotjx45yrz5sf9/dgetri.f90?dl=0
关于“第一个输入”的附加响应
https://www.dropbox.com/s/hximfoin977rmov/dgetri_piv4.f90?dl=0
这个最新的链接 (16-6) 包含两个数据集。在“第一个输入”中,您的方程式基本上是 4:6 行,即 1:3 / 7.5 + small_noise 行。
这个最新的代码示例在矩阵求逆期间和之后都进行了准确性检查。测试期间检查行更改是否正确,而后检查是“AA^-1 - I”和“A - (A^-1)^-1”,这更好地表明准确性差。
有趣的是,“第二输入”(有更多噪音)报告了相当准确的结果。无法获得 8 字节实数的逆需要一个相当人为的矩阵!类似地,随机数导出的系数示例显示出良好的准确性。
这些例子表明,我提出的准确性测试并不总是能识别定义不明确的方程关系。您检查逆以识别值的大变化也很有用。
鉴于方程的定义方式,我不确定您想要的结果是什么。
推荐阅读
- ruby - 如何在 Rspec 测试期间关闭 TCP 服务器?
- postgresql - postgresql - 根据当前时间选择记录
- amazon-dynamodb - 过滤器表达式中的 dynamodb AND 条件
- python - 犰狳 3D 网格的未完成渲染图像
- android - 点击选项卡导航器图标的监听器不起作用
- node.js - 使用 ssh 上传文件
- c - 将 DLL 与 C 程序正确捆绑
- javascript - Bot 将反应用户分配给 Discord 中的角色
- typescript - 使用单个 docker-compose 文件从自定义管道任务连接到 2 个 ACR
- visual-studio - 无法发布自包含的 Asp.net 5 核心项目