- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have a very simple question. I might better pose it with this sample program.
The output is 5.6, 0.1, 56, 55 (I did not show the zeroes after the decimal place which also appear in the display)
I understand that I am assigning single-precisionconstants to double precision variables and there could be issues with that. I tried using the /fpconstant option in the Configuration Property but the outputis unchanged.
One workaround is to add an infinitesimal value to c, such as 1.0e-8 to c beforing converting to an integer. But, I was wondering if there was some more elegant way.
Thanks!
[cpp]program test real*8 a,b,c integer d a = 5.6 b = 0.1 c = a/b d = int(c) write (*,*) a,b,c,d end[/cpp]
The output is 5.6, 0.1, 56, 55 (I did not show the zeroes after the decimal place which also appear in the display)
I understand that I am assigning single-precisionconstants to double precision variables and there could be issues with that. I tried using the /fpconstant option in the Configuration Property but the outputis unchanged.
One workaround is to add an infinitesimal value to c, such as 1.0e-8 to c beforing converting to an integer. But, I was wondering if there was some more elegant way.
Thanks!
Link Copied
2 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Try using nint(c) which gives the nearest integer.
FYI:
(1) The above program "as is" gives me 5.59999990463257, 0.100000001490116, 55.999982118607, 55. Use of nint(c) gives the last as 56.
(2) When using a = 5.6d0 and b = 0.1d0 I get the zeros after decimal as you mention but int(c) is still 55.
(3) When using real*4 and a = 5.6, b = 0.1, I get the zeros after decimal AND int(c) = 56.
I think you may want to read perils of real numbers and related articles by Steve Lionel and be careful with these round-off etc.
Abhi
FYI:
(1) The above program "as is" gives me 5.59999990463257, 0.100000001490116, 55.999982118607, 55. Use of nint(c) gives the last as 56.
(2) When using a = 5.6d0 and b = 0.1d0 I get the zeros after decimal as you mention but int(c) is still 55.
(3) When using real*4 and a = 5.6, b = 0.1, I get the zeros after decimal AND int(c) = 56.
I think you may want to read perils of real numbers and related articles by Steve Lionel and be careful with these round-off etc.
Abhi
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This isn't a real or double precision issue; its a fundamental feature of floating point representation.
Floating point numbers are broken down into the sum of positive and negative powers of 2, and many numbers
don't have exact representations.
.1 is, in fact, such a number. When you try to store .1 in a variable. The number stored is going to be
either slightly above or below the real value of .1
It appears the result of your calculation is actually something like 55.9999999... which gets rounded up
by the write statement. The INT function truncates rather than rounds, so the
.999999 part gets thrown out.
This is just something you have to learn to deal with. You should never, for example, test whether
a floating point number is exactly equal to another. Instead you should test whether the absolute value of the difference between the numbers is "close enough" for them to be considered to be the same.
Other languages (and at leat one version of Fortran that I have encounted) have fixed decimal arithmetic
available as an option. This uses a decimal rather than a binary representation, with numbers stored
to a special number of digits after the decimal point. This is popular for handling financial numbers that
need to be exact to the penny.
Floating point numbers are broken down into the sum of positive and negative powers of 2, and many numbers
don't have exact representations.
.1 is, in fact, such a number. When you try to store .1 in a variable. The number stored is going to be
either slightly above or below the real value of .1
It appears the result of your calculation is actually something like 55.9999999... which gets rounded up
by the write statement. The INT function truncates rather than rounds, so the
.999999 part gets thrown out.
This is just something you have to learn to deal with. You should never, for example, test whether
a floating point number is exactly equal to another. Instead you should test whether the absolute value of the difference between the numbers is "close enough" for them to be considered to be the same.
Other languages (and at leat one version of Fortran that I have encounted) have fixed decimal arithmetic
available as an option. This uses a decimal rather than a binary representation, with numbers stored
to a special number of digits after the decimal point. This is popular for handling financial numbers that
need to be exact to the penny.
Quoting - rdsrivathsa
I have a very simple question. I might better pose it with this sample program.
The output is 5.6, 0.1, 56, 55 (I did not show the zeroes after the decimal place which also appear in the display)
I understand that I am assigning single-precisionconstants to double precision variables and there could be issues with that. I tried using the /fpconstant option in the Configuration Property but the outputis unchanged.
One workaround is to add an infinitesimal value to c, such as 1.0e-8 to c beforing converting to an integer. But, I was wondering if there was some more elegant way.
Thanks!
[cpp]program test real*8 a,b,c integer d a = 5.6 b = 0.1 c = a/b d = int(c) write (*,*) a,b,c,d end[/cpp]
The output is 5.6, 0.1, 56, 55 (I did not show the zeroes after the decimal place which also appear in the display)
I understand that I am assigning single-precisionconstants to double precision variables and there could be issues with that. I tried using the /fpconstant option in the Configuration Property but the outputis unchanged.
One workaround is to add an infinitesimal value to c, such as 1.0e-8 to c beforing converting to an integer. But, I was wondering if there was some more elegant way.
Thanks!
Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page