For Programmers: Free Programming Magazines  


Home > Archive > Fortran > September 2005 > why system providing routies will provide different result in C++ and Fortran









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author why system providing routies will provide different result in C++ and Fortran
Qian Xin

2005-09-12, 6:58 pm

Now I make some converting- convert some fortran program to C++. I am
amazing about the little difference product by the C++ and fortran
program.

And after I check it deeply, I found that the + - * / operation does
not produce any difference. In C++ and Fortran, these operation will
give out identical result. So what I doubt is the system providing
routins such as exp, sqrt.

It definetly not a strange problem that in C++ and fortran, these
function will produce different result. But just because language
difference, they produce different result? or it is because the
difference in these function's implemention that make they producing
different result?

I write this message just wondering why they are different, and second
purpose is just complaining for these difference make me feel difficult
in converting Fortran code to C++.

Richard E Maine

2005-09-12, 6:58 pm

In article <1126551650.132468.249700@g44g2000cwa.googlegroups.com>,
"Qian Xin" <chianshin@gmail.com> wrote:

> It definetly not a strange problem that in C++ and fortran, these
> function will produce different result. But just because language
> difference, they produce different result? or it is because the
> difference in these function's implemention that make they producing
> different result?


Well, you don't actually say what the difference is. Nor do you show any
actual code. Between the two things, it is pretty much impossible to
give a definitive answer. For example, your list of possible causes
doesn't have anything like "user write code that didn't mean what he
thought it meant." There are plenty of ways for that to happen; some of
them involve misunderstanding of precision issues. Although I am
operating based on *VERY* little data, I'd place this pretty high on my
list of likely explanations. Indeed, the biggest piece of data I have is
the lack of data, which I might interpret as a failure to understand how
such things can be important.

You also didn't specify what you mean by "C++" and "Fortran". Have you
tried this for very compiler on every operating system (of course, I
know the answer to that)? Or are you referring to results from some
particular compiler? It makes a big difference. Some things are
properties of the language. Other things are properties of specific
compilers.

In particular, the language specifies things like whether a particular
literal constant is interpreted as single or double precision; that can
be a difference between C++ and Fortran. A specific compiler includes
the actual implementation of function libraries; that has nothing to do
with C++ vs Fortran. Different compilers for the same language can have
different function libraries, yet compilers for the different languages
might share parts of the same function library.

I've written a lot of words for what I'm afraid is little in the way of
concrete answer. I suppose the short version is that if you want a
precise answer, you need to ask a precise question.

--
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
Gordon Sande

2005-09-12, 6:58 pm

On 2005-09-12 16:00:50 -0300, "Qian Xin" <chianshin@gmail.com> said:

> Now I make some converting- convert some fortran program to C++. I am
> amazing about the little difference product by the C++ and fortran
> program.
>
> And after I check it deeply, I found that the + - * / operation does
> not produce any difference. In C++ and Fortran, these operation will
> give out identical result. So what I doubt is the system providing
> routins such as exp, sqrt.
>
> It definetly not a strange problem that in C++ and fortran, these
> function will produce different result. But just because language
> difference, they produce different result? or it is because the
> difference in these function's implemention that make they producing
> different result?


There may be diferences in the quality of the implementation of the
functions. That would be surprising for good implementions of both
languages. If a vendor has compilers for both languages they will
tend to reuse the code so there will be no differences.

> I write this message just wondering why they are different, and second
> purpose is just complaining for these difference make me feel difficult
> in converting Fortran code to C++.


You may be seeing differences in the order of evaluation of more
complex expressions. This will result in different roundoff errors.
Fortran compilers are allowed considerable freedom to rearrange
expressions.

Different orders of evaluation are common in Fortran when different
levels of optimization are requested by the user.

C and Fortran have subtle differences in their rules for when type
conversions are done if you have mixed precision expressions which
will then result if different roundoff. It is possible that the
different systems have chosen different rounding options for the
hardware. This may also involve the compiler using a hidden extended
precision mode for its temporaries.

Changes due to differing roundoff are common in Fortran when changing
compiler, either a different vendor, just a newer version or even only
a different optimization level.

There are many subtle ways for arithmetic to produce slightly diferent
result beyond the ways you have mentioned. I have listed a few.

If the differences accumulate you may be seeing the symptoms of an
unstable algorithm in which case your problems are not with choice
of programming language but rather of numerical method.

Ask google about a paper called
"What every computer scientist should know about floating-point"
for a nice introducion to the topic.










Ian Chivers

2005-09-12, 6:58 pm

c/c++ built in maths functions will convert/promote any argument to double
and
return a double result.

literal numeric constants (e.g. 2.0) in fortran are c++ float.
in c++ they are double.

trig function evaluation of sin/cos/tan of 90 degrees
in fortran (of c++ float) returns a result with cos and tan in the wrong
quadrant.
this is not a defect of fortran. try single precision (32 bit) trig
evaluation
in most languages and the cos and tan results will return results
in the wrong quadrant.

you need to develop an understanding of floating points maths.

the later post points to a very good paper on this whole issue.

"Qian Xin" <chianshin@gmail.com> wrote in message
news:1126551650.132468.249700@g44g2000cwa.googlegroups.com...
> Now I make some converting- convert some fortran program to C++. I am
> amazing about the little difference product by the C++ and fortran
> program.
>
> And after I check it deeply, I found that the + - * / operation does
> not produce any difference. In C++ and Fortran, these operation will
> give out identical result. So what I doubt is the system providing
> routins such as exp, sqrt.
>
> It definetly not a strange problem that in C++ and fortran, these
> function will produce different result. But just because language
> difference, they produce different result? or it is because the
> difference in these function's implemention that make they producing
> different result?
>
> I write this message just wondering why they are different, and second
> purpose is just complaining for these difference make me feel difficult
> in converting Fortran code to C++.
>



e p chandler

2005-09-12, 6:58 pm

Qian Xin wrote:
> Now I make some converting- convert some fortran program to C++. I am
> amazing about the little difference product by the C++ and fortran
> program.
>
> And after I check it deeply, I found that the + - * / operation does
> not produce any difference. In C++ and Fortran, these operation will
> give out identical result. So what I doubt is the system providing
> routins such as exp, sqrt.
>


[snip]

Without seeing your test programs, it is difficult to guess, but here
is one idea. I've tested the 4.1.0 versions of gcc (C) and gfortran
(Fortran).

consider the following programs:

C:\gfortran>type foo1.c
#include <stdio.h>
#include <math.h>
int i;
main(){
for(i=0;i<6;i++){
printf(" %2d %17.15f\n",i,sqrt(i));
}
}

C:\gfortran>type foo2.f
do i=0,5
print '(1x,i2,1x,f17.15)',i,sqrt(real(i))
end do
end

C:\gfortran>type foo3.f
do i=0,5
print '(1x,i2,1x,f17.15)',i,sqrt(dble(i))
end do
end

C:\gfortran>C:\gfortran>make

C:\gfortran>gcc foo1.c -Iinclude -o foo1

C:\gfortran>gfortran foo2.f -o foo2

C:\gfortran>gfortran foo3.f -o foo3
C:\gfortran>foo1
0 0.000000000000000
1 1.000000000000000
2 1.414213562373095
3 1.732050807568877
4 2.000000000000000
5 2.236067977499790

C:\gfortran>foo2
0 0.000000000000000
1 1.000000000000000
2 1.414213538169861
3 1.732050776481628
4 2.000000000000000
5 2.236068010330200

C:\gfortran>foo3
0 0.000000000000000
1 1.000000000000000
2 1.414213562373095
3 1.732050807568877
4 2.000000000000000
5 2.236067977499790

C:\gfortran>

In the C program, sqrt returns a "double". In the Fortran program, the
return type is the same as the type of the argument. In the first
program, it is real or "float" in C terminology. In the second program
it is double precision or "double" in C.

-- Elliot

Ian Chivers

2005-09-14, 7:00 pm

Here is a test program

program
---------

program trigtest
implicit none
integer , dimension(15) :: angles= &
(/- 1,0,1,29,30,31,44,45,46,59,60,61,89,90,9
1/)
real :: pi
real :: r
integer :: i
pi=4.0*atan(1.0)
do i=1,15
r=pi*angles(i)/180
print *,angles(i),' ',sin(r),' ',cos(r),' ',tan(r)
end do
end program trigtest

end program
--------------

Here is the intel output

-1 -1.7452406E-02 0.9998477 -1.7455066E-02
0 0.0000000E+00 1.000000 0.0000000E+00
1 1.7452406E-02 0.9998477 1.7455066E-02
29 0.4848096 0.8746197 0.5543091
30 0.5000000 0.8660254 0.5773503
31 0.5150381 0.8571673 0.6008607
44 0.6946584 0.7193398 0.9656888
45 0.7071068 0.7071068 1.000000
46 0.7193398 0.6946583 1.035530
59 0.8571673 0.5150381 1.664279
60 0.8660254 0.5000000 1.732051
61 0.8746197 0.4848096 1.804048
89 0.9998477 1.7452383E-02 57.29004
90 1.000000 -4.3711388E-08 -2.2877332E+07
91 0.9998477 -1.7452471E-02 -57.28975

note the sign at 90 degrees of the cos and tan.

we've found we get similar results
with all of the compilers we currently use.

it is one of the examples that Jane Sleightholme
and I have developed to help beginners
understand some of the problems they will
encounter with floating point maths.

"Rich Townsend" <rhdt@barVOIDtol.udel.edu> wrote in message
news:dg4sqi$gjb$1@scrotar.nss.udel.edu...
> Ian Chivers wrote:
>
> I'm not sure what you mean by 'the wrong quadrant'. The trig functions
> return a number between -1 and 1 (SIN and COS) or -Inf and +Inf (TAN);
> there is no notion of 'quadrant', since the return value is not an angular
> measure.
>
> If you instead mean the inverse trig functions, then the Fortran standard
> is quite explicit about which quandrant the returned angular measure falls
> within. To get a 'correct' quadrant, you should be using the ATAN2()
> function (there is no ACOS2 or ASIN2, since there is no sensible way to
> define two-argument variants of ACOS and ASIN).
>
> cheers,
>
> Rich



Ian Chivers

2005-09-14, 7:00 pm

I've just run the c++ example below with
cygwin g++ 3.4.4.

#include <iostream>
#include <cmath>
using namespace std;

int main()
{
float angle_r;
int angle_d;
int angles [] ={ -1, 0, 1,
29,30,31,
44,45,46,
59,60,61,
89,90,91 };

float pi=4*atan(1.0);

for(int i=0;i<15;i++)
{
angle_d=angles[i];
angle_r=angle_d*pi/180;
cout << angle_d << " " ;
cout.width(15);cout.precision(10);cout << sin(angle_r)<< " " ;
cout.width(15);cout.precision(10);cout << cos(angle_r)<< " " ;
cout.width(15);cout.precision(10);cout << tan(angle_r)<< " " << endl;
}

return 0;
}

this now returns the following output.

-1 -0.0174524063 0.9998476952 -0.01745506479
0 0 1 0
1 0.0174524063 0.9998476952 0.01745506479
29 0.4848096152 0.8746197099 0.5543090439
30 0.5000000126 0.8660253965 0.5773502886
31 0.5150381048 0.8571672827 0.6008606666
44 0.6946583715 0.7193397993 0.9656887777
45 0.7071067966 0.7071067657 1.000000044
46 0.7193398297 0.6946583401 1.035530401
59 0.8571673052 0.5150380674 1.664279515
60 0.8660254184 0.4999999748 1.732050924
61 0.8746197311 0.484809577 1.804047966
89 0.9998476956 0.01745238308 57.29003832
90 1 -4.371139e-08 -22877332.43
91 0.999847694 -0.01745247049 -57.2897513

I stopped teaching c++ in 2002. when
did this behaviour come into C++ compilers?

"Tim Prince" <tprince@nospamcomputer.org> wrote in message
news:yzrVe.501$Jm.439@newssvr27.news.prodigy.net...
> Ian Chivers wrote:
> This is true of "traditional" C and C++. Most C++ compilers support
> versions corresponding to the various floating point data types.
> C differs from C++ in supporting "type generic" intrinsic functions
> <tgmath.h>, somewhat analogous to Fortran. Many C++ compilers support
> mixing it in as an extension. OP may have meant to exclude it by
> specifying C++.
> I agree that the difference in default types (double in C++, commonly
> single in Fortran) is among the issues OP should be considering.
>
> It is not unusual for C and Fortran to share the math function library, in
> which case difference in results is attributable to cockpit error.



Ian Chivers

2005-09-14, 7:00 pm

my main occupation is teaching programming
to people with little or no numeric background.

the mathematical value of the cosine 90 degrees is 0 and
the tangent of 90 degrees is infinity.

to the complete beginner to programming the actual
values returned don't make much sense.

i don't claim that the values are wrong, but that they
are not at all obvious to the beginner.

"Brooks Moses" <bmoses-nospam@cits1.stanford.edu> wrote in message
news:4328831B.1050902@cits1.stanford.edu...
> Ian Chivers wrote:
> [...]
> [...]
>
> Yes. What's wrong with it?
>
> Clearly, r is an approximation to pi/4 in any limited-precision
> calculation, and thus these values are values for some angle that's nearly
> but not exactly 90 degrees. Thus, I can't see any reason to claim that
> either sign would be wrong here, unless you have some specific claim about
> what side of pi/4 r happens to lie on.
>
> - Brooks
>
>
> --
> The "bmoses-nospam" address is valid; no unmunging needed.



Ian Chivers

2005-09-14, 7:00 pm

it isn't just a question of + or - but also the fact that it isn't zero.
if you have a calculation based on trig functions
then the student needs to be wary with floating point maths.

we also get the students to try a calculator
and excel. the answer differ.

"Rich Townsend" <rhdt@barVOIDtol.udel.edu> wrote in message
news:dga43a$45k$1@scrotar.nss.udel.edu...
> Ian Chivers wrote:
>
> I'm still not following your point. COS(90) should ideally return zero, in
> reality it returns some number close to zero. This number could either be
> positive or negative. Why in your eyes should the number be positive?
>
> cheers,
>
> Rich



Ian Chivers

2005-09-14, 7:00 pm

the following program

program trigtest
implicit none
integer , dimension(15) :: angles= &
(/- 1,0,1,29,30,31,44,45,46,59,60,61,89,90,9
1/)
real :: pi
real :: r,s,c,t
double precision :: dr
integer :: i
pi=4.0d0*atan(1.0d0)
do i=1,15
r=pi*angles(i)/180
dr=r
print *,angles(i),' ',sin(r),' ',cos(r),' ',tan(r)
s=sin(dr)
c=cos(dr)
t=tan(dr)
print *,angles(i),' ',s,' ',c,' ',t
end do
end program trigtest

generates the following output

-1 -1.745241E-02 0.999848 -1.745507E-02
-1 -1.745241E-02 0.999848 -1.745507E-02
0 0.00000 1.00000 0.00000
0 0.00000 1.00000 0.00000
1 1.745241E-02 0.999848 1.745507E-02
1 1.745241E-02 0.999848 1.745507E-02
29 0.484810 0.874620 0.554309
29 0.484810 0.874620 0.554309
30 0.500000 0.866025 0.577350
30 0.500000 0.866025 0.577350
31 0.515038 0.857167 0.600861
31 0.515038 0.857167 0.600861
44 0.694658 0.719340 0.965689
44 0.694658 0.719340 0.965689
45 0.707107 0.707107 1.00000
45 0.707107 0.707107 1.00000
46 0.719340 0.694658 1.03553
46 0.719340 0.694658 1.03553
59 0.857167 0.515038 1.66428
59 0.857167 0.515038 1.66428
60 0.866025 0.500000 1.73205
60 0.866025 0.500000 1.73205
61 0.874620 0.484810 1.80405
61 0.874620 0.484810 1.80405
89 0.999848 1.745238E-02 57.2900
89 0.999848 1.745238E-02 57.2900
90 1.00000 -4.371139E-08 -2.287733E+07
90 1.00000 -4.371139E-08 -2.287733E+07
91 0.999848 -1.745247E-02 -57.2898
91 0.999848 -1.745247E-02 -57.2898

and verifies the claim you make. mea culpa.

:-(

"Brooks Moses" <bmoses-nospam@cits1.stanford.edu> wrote in message
news:4328847F.7040309@cits1.stanford.edu...
> Ian Chivers wrote:
> [...]
>
> What behavior? If you're talking about the stuff regarding promoting the
> float arguments to double and evaluating the result in double precision:
> do you have some evidence that -4.37e-08 is _not_ a
> double-precision-accurate calculation of the cosine of the
> single-precision number closest to pi/4?
>
> - Brooks
>
>
> --
> The "bmoses-nospam" address is valid; no unmunging needed.



andy2O

2005-09-14, 7:00 pm

Ian Chivers wrote:

> my main occupation is teaching programming
> to people with little or no numeric background.
>
> the mathematical value of the cosine 90 degrees is 0 and
> the tangent of 90 degrees is infinity.
>
> to the complete beginner to programming the actual
> values returned don't make much sense.
>
> i don't claim that the values are wrong, but that they
> are not at all obvious to the beginner.
>


OK, even good trig functions can only return closest floating point
approximations - and I'm all for teaching it to all who will listen...

But on reading the sample code, my first reaction was that the much
bigger and more straightforward error would be if someone assumed that
when angles==90, that the (rational) floating point value of r could
ever be identical to pi/2 (an irrational number)....

Clearly r==pi/2 is impossible for floating point r, so a (hypothetical)
perfect precision cos function *should never* return cos(r)==0 for a
floating point value of r. Infact if it did return cos(r)==0, wouldn't
that be certain evidence that the cos function in question was not of
perfect precision...

(I think best go off to reread "What every computer scientist should
know about floating point arithmetic" myself...)

Yours,
Andy.
[color=darkred]
> "Brooks Moses" <bmoses-nospam@cits1.stanford.edu> wrote in message
> news:4328831B.1050902@cits1.stanford.edu...

John Harper

2005-09-14, 9:57 pm

In article <1126735520.733036.224700@g49g2000cwa.googlegroups.com>,
andy2O <andy2O@hotmail.com> wrote:

>(I think best go off to reread "What every computer scientist should
>know about floating point arithmetic" myself...)


Good idea, but when I looked at it just now it mentioned c99 but its
latest Fortran was f77.

Being an applied mathematician, it often seems to me that computer
science is everything you can do in a computer except numerical
analysis and floating-point arithmetic. Maybe I should add Fortran
to that list.

John Harper, School of Mathematics, Statistics and Computer Science,
Victoria University, PO Box 600, Wellington, New Zealand
e-mail john.harper@vuw.ac.nz phone (+64)(4)463 5341 fax (+64)(4)463 5045
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2009 codecomments.com