再次:C ++和Fortran之间的链接导致错误的结果 [英] Again: linking between C++ and Fortran results in incorrect result

查看:84
本文介绍了再次:C ++和Fortran之间的链接导致错误的结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有时候我在C ++和Fortran

程序之间的链接方面遇到了问题。使用Fortran

关键字序列解决了这个问题(使用来自此新闻组的输入)与派生类型(假设连续空间)。


现在我又遇到了问题。为了显示我创建的问题,我创建了一个小程序,这次没有数据结构在

C ++和Fortran之间传递。


以下是程序的样子


file read_do_calc.f =================== subroutine read_do_calc()


双精度:: a,b,c,d,e,f,val


open(60,file =''binary_file '',status =''unknown'',form =''unformatted'')

阅读(60)a

阅读(60)b

阅读(60)c

阅读(60)d

阅读(60)e

阅读(60)f

关闭(60)

写(*,*)a,'''',b,'''',c,'''',d, '''',e,'''',f


val = a +(b * c * d *(e * e))* f

写(*,*)''val ='',val


返回

endfile fort_main.f ========= =======程序主要


调用read_do_calc()


endprogram mainfile main.cpp ==== ========= externC {

void read_do_calc_(void);

}


int main(无效)

{

read_do_calc_();


返回0;

}编译read_do_calc.f

ifort - c read_do_calc.f


创建fortran programifort -o fort_prog fort_main.f read_do_calc.o


创建c ++程序(使用icc或g ++,在我的

案例中没关系)icc -o cpp_prog main.cpp
read_do_calc.o -L / lusr / share / software / intel / lib -lifcore



下面给出的两个程序的输出

./fort_prog
-0.430331482911935 1.00000000000000 -0.774596669241483

-1.00000000000000 2.00000000000000 0.138888888888889

val = 0.000000000000000E + 000

./cpp_prog
-0.430331482911935 1.00000000000000 -0.774596669241483

-1.00000000000000 2.00000000000000 0.138888888888889
val = -6.965998958219366E-018注意变量val的值。在两种情况下是不同的
。我使用的ifort版本是isifort --versionifort(IFORT)9.0 20050430Copyright(C)1985-2005 Intel



公司。保留所有权利.icc的版本是> icc --versionicc

(ICC)9.0 20050430Copyright(C)1985-2005 Intel Corporation。所有权利

保留。文件binary_file被附上。从那个计算看起来像

子程序read_do_calc()的非平凡程序中捕获了

。有人可以帮助我吗?我错了什么

这次?谢谢.NM

解决方案

NM写道:

有时前我在C ++和Fortran
程序之间的链接方面存在问题。使用Fortran
关键字序列解决了这个问题(使用来自此新闻组的输入)。与派生类型(假设连续空间)。
现在我又遇到了问题。为了显示我创建的小程序的问题,这次在C ++和Fortran之间没有传递数据结构。


(剪辑)

val = a +(b * c * d *(e * e))* f


(剪辑)

-0.430331482911935 1.00000000000000 -0.774596669241483
-1.00000000000000 2.00000000000000 0.138888888888889
val = 0.000000000000000E + 000


(剪辑)

-0.430331482911935 1.00000000000000 -0.774596669241483
-1.00000000000000 2.00000000000000 0.138888888888889
val = -6.965998958219366E-018
注意变量val的值在这两种情况下是不同的。我正在使用的ifort版本是




关于这一点,我可以说很多事情。


首先,使用主程序

的语言总是做I / O可能更好。有时需要初始化I / O系统。

这比以前少了一个问题,因为许多人使用一个库

来进行实际的I / O在这两种情况下。


一般来说,一个人不应该依赖浮点数的确切结果,特别是在减去非常相似的数字的时候。


我在这种情况下的猜测是Fortran主程序将

浮点处理器设置为53位精度,其中C ++设置

或离开它64.允许编译器以比所要求的更精确的方式执行
算术的规则是复杂的,

以及C ++和Fortran之间的不同。


无论如何,期待一个答案或另一个答案浮动

点,我相信是没有根据的。


- 格伦


在文章< dg ********** @ news.cs.utexas.edu>," NM" < nm@nm.com>写道:


.....

val = a +(b * c * d *(e * e))* f
....

./ fort_prog



.... val = 0.000000000000000E + 000 < blockquote class =post_quotes> ./ cpp_prog


val = -6.965998958219366E-018
请注意变量val的值。两种情况不同。


肯定不是*非常*不同。不同之处在于双精度准确度对于b $ b的预期是什么。

有谁可以帮助我?这次我做错了什么?




你所做的错误是希望从b
浮点运算得到完美的准确性。这与编程

语言几乎没有关系。它是典型计算机算术实现的基本属性。你需要阅读这个主题。

文件< http://docs.sun.com/source/806-3568/ncg_goldberg.html>是一个优秀的,经常被引用的主题治疗方法(实际上,在大约一天左右的时间里,它在另一个帖子中引用了

)。


除了那些基本材料,你还需要了解一个

给定的表达式可能会在不同的

编译器中以不同的方式实现,甚至使用相同编译器的不同选项。那些不同的实现可能涉及不同的排序

操作或

寄存器中中间值存储的差异。这些差异可以并且确实经常导致
四舍五入的差异。


由于这些因素,期望结果是错误的
除了某些特殊的

情况外,
浮点运算确切......而且你没有这些情况。浮点

操作通常应视为近似值。您可以根据需要选择适当的精度来保证应用程序的近似值合理

,但您无法合理地预期事情是准确的。

你做错了什么是期待确切的结果。


您所看到的差异大约是预期的大小

简单的舍入情况错误。对于数值不稳定的算法,

这种微小的差异有时会变得非常大。也许

这是你在实际的

申请中引起你注意的问题。 (这通常表明东方有理由质疑所用算法的适用性)。测试精确

值的算法表现得特别糟糕。


如果你说我理解这一切,但......(插入)

这里的任何东西),然后我害怕你真的不明白。它确实是&b $ b跟随但是之后的内容并不重要。特别是,

的任何变体,但它在两种语言中都是相同的表达式。表示

你真的不明白。


-

Richard Maine |良好的判断来自经验;

电子邮件:我的第一个.last org.domain |经验来自糟糕的判断。

org:nasa,domain:gov | - 马克吐温


Richard E Maine写道:


(剪辑)

肯定不是*非常*不同。关于双精度精度的预期差异是正确的。


(剪辑)

你所做的错误是希望从浮点算术中获得完美的准确性。这与编程
语言几乎没有关系。它是典型的计算机算法实现的基本属性。你需要阅读这个主题。
文件< http://docs.sun.com/source/806-3568/ncg_goldberg.html>是一个优秀的,经常被引用的主题治疗方法(实际上,它在大约一天前的另一个主题中引用了
)。


我100%同意,如果他期望更多浮点数,那就是错误的b $ ba $

除了那个基本的材料,您还需要了解,给定的表达式可能在不同的编译器中以不同的方式实现,甚至可能在同一编译器的不同选项中实现。那些不同的实现可能涉及诸如操作的不同排序或者在寄存器中存储中间值的差异之类的事情。这些差异可能并且确实经常导致四舍五入的差异。


但在这种情况下,它是相同的目标程序。他从C ++或Fortran主程序调用

子程序,只编译一次。

所有计算都在子程序中完成。

由于这些因素,除了某些特殊的情况外,期望浮点运算的结果是准确的是错误的...而且你没有这些情况。浮点
操作通常应视为近似值。您可以根据需要选择合适的精度来保持应用程序的近似值,但是您无法合理地预期事情是准确的。
您做错了什么是期待准确的结果。


是的。请注意,同一程序中不同行的相同

表达式也存在类似差异。


(剪辑)

如果你说我理解所有这一切,但......(在这里插入任何东西),那么我恐怕你们真的不明白。它真的没关系但是之后的内容。特别是,两种语言中的相同表达都是
的任何变体。会表明你并不理解。




我不完全确定我理解x87漂浮的方式

点处理器已初始化,但甚至可能运行相同的.EXE文件并获得不同的结果。
。如果

库没有初始化x87控制寄存器,并且

操作系统没有,那么你可以得到之前的任何东西。


如果你想要精确的结果,不要使用浮点数。


- glen


Sometimes ago I was having a problem in linking between C++ and Fortran
program. That was solved (using input from this newsgroup) using the Fortran
keyword "sequence" with the derived types (to assume contiguous space).

Now I am having problem again. In order to show the problem I have created
small program and this time there is no data straucture being passed between
C++ and Fortran.

Here is how the program looks like

file read_do_calc.f=================== subroutine read_do_calc()

double precision :: a,b,c,d,e,f,val

open(60,file=''binary_file'',status=''unknown'',form='' unformatted'')
read(60) a
read(60) b
read(60) c
read(60) d
read(60) e
read(60) f

close(60)
write(*,*) a,'' '',b,'' '',c,'' '',d,'' '',e,'' '',f

val = a + (b*c*d*(e*e))*f
write(*,*) ''val = '',val

return
endfile fort_main.f================ program main

call read_do_calc()

endprogram mainfile main.cpp============= extern "C" {
void read_do_calc_(void);
}

int main(void)
{
read_do_calc_();

return 0;
} compile read_do_calc.f

ifort -c read_do_calc.f
create the fortran programifort -o fort_prog fort_main.f read_do_calc.o
create the c++ program (either using icc or g++ , it did not matter in my
case)icc -o cpp_prog main.cpp
read_do_calc.o -L/lusr/share/software/intel/lib -lifcore

output of the two programs given below
./fort_prog -0.430331482911935 1.00000000000000 -0.774596669241483
-1.00000000000000 2.00000000000000 0.138888888888889
val = 0.000000000000000E+000
./cpp_prog -0.430331482911935 1.00000000000000 -0.774596669241483
-1.00000000000000 2.00000000000000 0.138888888888889
val = -6.965998958219366E-018Notice the value of the variable "val" is
different in the two cases.The version of ifort I am using isifort --versionifort (IFORT) 9.0 20050430Copyright (C) 1985-2005 Intel


Corporation. All rights reserved.and the version of icc is>icc --versionicc
(ICC) 9.0 20050430Copyright (C) 1985-2005 Intel Corporation. All rights
reserved.The file "binary_file" is attached. The values there was captured
from a nontrivial program whose computation looks like that of the
subroutine read_do_calc().Can anyone please help me? What am I doing wrong
this time? Thanks.NM


解决方案

NM wrote:

Sometimes ago I was having a problem in linking between C++ and Fortran
program. That was solved (using input from this newsgroup) using the Fortran
keyword "sequence" with the derived types (to assume contiguous space). Now I am having problem again. In order to show the problem I have created
small program and this time there is no data straucture being passed between
C++ and Fortran.
(snip)
val = a + (b*c*d*(e*e))*f
(snip)
-0.430331482911935 1.00000000000000 -0.774596669241483
-1.00000000000000 2.00000000000000 0.138888888888889
val = 0.000000000000000E+000
(snip)
-0.430331482911935 1.00000000000000 -0.774596669241483
-1.00000000000000 2.00000000000000 0.138888888888889
val = -6.965998958219366E-018 Notice the value of the variable "val" is
different in the two cases.The version of ifort I am using is



There are a number of things I could say about this.

First, it is probably better to always do I/O using the language of
the main program. Sometimes the I/O system needs to be initialized.
This is less a problem than it used to be, as many use one library
to do the actual I/O in both cases.

In general, one should not rely on exact results from floating point,
especially when subtracting very similar numbers.

My guess in this case is that the Fortran main program sets the
floating point processor to 53 bit precision, where C++ sets
or leaves it at 64. The rules for allowing the compiler to do
arithmetic with more precision than is asked for are complicated,
and different between C++ and Fortran.

In any case, expecting one answer or the other from floating
point is, I believe, unwarranted.

-- glen


In article <dg**********@news.cs.utexas.edu>, "NM" <nm@nm.com> wrote:

.....

val = a + (b*c*d*(e*e))*f ....

./fort_prog


.... val = 0.000000000000000E+000

./cpp_prog

val = -6.965998958219366E-018
Notice the value of the variable "val" is different in the two cases.
It sure isn''t *VERY* different. The difference is right about what one
would expect for double precision accuracy.
Can anyone please help me? What am I doing wrong this time?



What you are doing wrong is expecting perfect accuracy from
floating-point arithmetic. This has very little to do with programming
languages. It is instead a fundamental property of typical computer
implementations of arithmetic. You need to read up on that subject. The
document <http://docs.sun.com/source/806-3568/ncg_goldberg.html> is an
excellent and oft-cited treatment of the subject (in fact, it was cited
in another thread here just a day or so ago).

In addition to that basic material, you also need to understand that a
given expression might be implemented differently in different
compilers, or even with different options of the same compiler. Those
different implementations can involve such things as different ordering
of operations or differences in storage of intermediate values in
registers. These differences can and do often result in differences in
rounding.

Because of these factors, it is a mistake to expect the results of
floating point operations to be exact except in some special
circumstances... and you don''t have those circumstances. Floating point
operations should generally be viewed as approximations. You can select
an appropriate precision as needed to keep the approximations reasonable
for an application, but you can''t reasonably expect things to be exact.
What you are doing wrong is expecting exact results.

The differences you are seeing are right around the size expected from
simple cases of rounding error. With numerically unstable algorithms,
such small differences can sometimes grow to be quite large. Perhaps
that''s what drew your attention to the problem in the actual
application. (That generally indicates at east reason to question the
suitability of the algorithm used). ALgorithms that test for exact
values can behave particularly poorly.

And if you say something like "I understand all that, but...(insert
anything here)", then I''m afraid you didn''t really understand. It really
doesn''t matter what follows the "but". In particular, any variation of
"but it was the same expression in both languages" would indicate that
you didn''t really understand.

--
Richard Maine | Good judgment comes from experience;
email: my first.last at org.domain | experience comes from bad judgment.
org: nasa, domain: gov | -- Mark Twain


Richard E Maine wrote:

(snip)

It sure isn''t *VERY* different. The difference is right
about what one would expect for double precision accuracy.
(snip)
What you are doing wrong is expecting perfect accuracy from
floating-point arithmetic. This has very little to do with programming
languages. It is instead a fundamental property of typical computer
implementations of arithmetic. You need to read up on that subject. The
document <http://docs.sun.com/source/806-3568/ncg_goldberg.html> is an
excellent and oft-cited treatment of the subject (in fact, it was cited
in another thread here just a day or so ago).
I 100% agree, if he expects more from floating point, that is
a mistake.
In addition to that basic material, you also need to understand that a
given expression might be implemented differently in different
compilers, or even with different options of the same compiler. Those
different implementations can involve such things as different ordering
of operations or differences in storage of intermediate values in
registers. These differences can and do often result in differences in
rounding.
In this case, though, it is the same object program. He calls the
subroutine, compiled only once, from a C++ or Fortran main program.
All the calculation is done in the subroutine.
Because of these factors, it is a mistake to expect the results of
floating point operations to be exact except in some special
circumstances... and you don''t have those circumstances. Floating point
operations should generally be viewed as approximations. You can select
an appropriate precision as needed to keep the approximations reasonable
for an application, but you can''t reasonably expect things to be exact.
What you are doing wrong is expecting exact results.
Yes. Note that similar differences have been seen for the same
expression at a different line in the same program.

(snip)
And if you say something like "I understand all that, but...(insert
anything here)", then I''m afraid you didn''t really understand. It really
doesn''t matter what follows the "but". In particular, any variation of
"but it was the same expression in both languages" would indicate that
you didn''t really understand.



I am not completely sure I understand the way the x87 floating
point processor is initialized, but it might even be possible
to run the same .EXE file and get different results. If the
library doesn''t initialize the x87 control register, and the
OS doesn''t, you get whatever was there before.

If you want exact results don''t use floating point.

-- glen


这篇关于再次:C ++和Fortran之间的链接导致错误的结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆