1

In Fortran, I want to be able to round a large double precision float to the nearest integer. I attempt this as follows,

PROGRAM rounding
IMPLICIT NONE
INTEGER, PARAMETER :: DP = 8
REAL(KIND=DP) :: value

value = 12345678987.123456

print *, CEILING(value)

END PROGRAM ROUNDING 

However, this does not output the correct answer, but instead gives -2147483648. I appreciate that this is related to the nature and precision of floating points, but rounding a number like this seems a reasonable goal.

Can anyone point me in the right direction?

user1887919
  • 829
  • 2
  • 9
  • 24
  • Minor note: if `value` is a double precision number, it is better to write `value = 12345678987.123456_dp`. Without the `_dp`, you are assigning a single precision number to `value` and some of the digits are lost. In your case, the difference in the resulting integer is `12345678848` vs `12345678988`. – Raul Laasner Aug 14 '17 at 17:32

1 Answers1

1

The integer variable returned by ceiling() is of a too small kind to contain the value. You have to tell ceiling to produce an integer of a larger kind. Otherwise it uses the default integer.

For example by

print *, CEILING(value, kind=dp)

(assuming there exist such kind, but it should exist, if DP is selected sensibly)

Do note that kind=8 is ugly and not portable. You should not use literal constants such as 8. There is no guarantee that any such kind exist.

So I would use:

INTEGER, PARAMETER :: DP = kind(1.d0)

For the integer kind you can use SELECTED_INT_KIND to select the kind with enough digits like

INTEGER, PARAMETER :: IP = SELECTED_INT_KIND(15)

print *, CEILING(value, kind=IP)

or use any other method from Fortran: integer*4 vs integer(4) vs integer(kind=4)

  • The original question asks for 'nearest integer', which is more like `NINT` than `CEILING`. But the rest of the answer, which is the important part, is correct. – Ross Aug 14 '17 at 18:07