Skip to content

Numbers ​

The kinds ​

use stringifor exports the portable kinds of PENF:

ParameterTypeBytes
I1Pinteger1
I2Pinteger2
I4Pinteger4
I8Pinteger8
R4Preal4
R8Preal8
R16Preal16
  • R16P is supported (in the assignment and in to_number) when the library is compiled with the -DPENF_R16P preprocessor flag.
  • I2P is not supported when the _NVF macro is defined (NVIDIA Fortran compatibility).

Is it a number? ​

f90
program number_check
!< Is it a number?
use stringifor
implicit none
type(string) :: s(6)
integer      :: i

s(1) = '42' ; s(2) = '-3.14' ; s(3) = '6.02e23' ; s(4) = '1.' ; s(5) = '12 apples' ; s(6) = '007'
print '(A)', 'string      number integer real digit'
do i = 1, size(s)
  print '(A,4(L1,6X))', s(i)%fill(width=12, right=.true., filling_char=' ')//'', &
        s(i)%is_number(), s(i)%is_integer(), s(i)%is_real(), s(i)%is_digit()
enddo
endprogram number_check
$ number_check
string      number integer real digit
42          T      T      F      T
-3.14       T      F      T      F
6.02e23     T      F      T      F
1.          T      F      T      F
12 apples   F      F      F      F
007         T      T      F      T
MethodTrue if the string is
is_integer([allow_spaces])an integer, with an optional sign
is_real([allow_spaces])a real: digits with a decimal point or an exponent (or both); an integer is not a real
is_number([allow_spaces])an integer or a real
is_digit()made of digits only

Leading and trailing blanks are accepted, unless allow_spaces=.false..

From a string to a number ​

f90
program number_cast
!< From a string to a number.
use stringifor
implicit none
type(string) :: s
real(R8P)    :: x
integer(I4P) :: n

s = '3.4e2'
if (s%is_number()) x = s%to_number(kind=1._R8P)   ! the kind of the argument selects the result
print '(F0.1)', x
s = '42'
if (s%is_integer()) n = s%to_number(kind=1_I4P)
print '(I0)', n + 1
x = s%to_number(kind=1._R8P)                      ! an integer string is a valid real
print '(F0.1)', x
endprogram number_cast
$ number_cast
340.0
43
42.0

to_number(kind) returns the number in the string. The argument selects the kind of the result and nothing else: its value is ignored, pass any constant of the wanted kind (1_I4P, 1._R8P). A cast to a real kind accepts a real or an integer string, a cast to an integer kind an integer string.

A plain decimal number (a sign, at most 18 significant digits, a decimal point, an exponent) is converted without the read statement when the result is exact: any integer in the range of the kind, and a real whose digits and power of ten are exact in the kind (up to 15 digits and 1e22 for R8P), a single correctly rounded operation. Every other string goes through read: the result is the same, the plain numbers are about twenty times faster.

WARNING

On a string that does not hold a suitable number the result is 0 for an integer kind and a quiet NaN for a real kind: check with is_number or is_integer first to tell a parsed 0 from a failure, or use read_number.

With an error status ​

f90
program checked_cast
!< Numbers read from strings, with an error status.
use stringifor
implicit none
type(string)      :: fields(3)
real(R8P)         :: value
integer           :: iostat
character(len=99) :: iomsg
integer           :: f

fields(1) = '3.25'
fields(2) = 'n/a'
fields(3) = '1e3'
do f = 1, size(fields)
  call fields(f)%read_number(value, iostat=iostat, iomsg=iomsg)
  if (iostat == 0) then
    print '(A,F8.2)', fields(f)//' -> ', value
  else
    print '(A)', fields(f)//' -> error: '//trim(iomsg)
  endif
enddo
endprogram checked_cast
$ checked_cast
3.25 ->     3.25
n/a -> error: the string is not a number
1e3 ->  1000.00

read_number(number[, iostat][, iomsg]) is a subroutine: the kind is the one of number, and the failure is reported as by a read statement, iostat being 0 on success and positive otherwise, iomsg explaining it. On failure number gets the same value as to_number, 0 or NaN. It is elemental: on an array of strings, number and iostat are arrays.

From a number to a string ​

f90
program number_to_string
!< From a number to a string.
use stringifor
implicit none
type(string) :: s

s = 42
print '(A)', s//''
s = -127_I1P
print '(A)', s//''
s = 2.5_R4P
print '(A)', s//''
s = 1._R8P/3._R8P
print '(A)', s//''
s = 255
print '(A)', s%hex()//' '//s%hex(uppercase=.true.)
s = -1
print '(A)', s%hex(bits=16)//''                   ! two's complement on 16 bits
endprogram number_to_string
$ number_string
+42
-127
+0.250000000E+01
+0.33333333333333331E+000
ff FF
ffff
  • An integer is written with its sign; a real with its sign and all the significant digits of its kind, so the string holds the nearest representable value. For another layout, write the number with a format into a character.
  • hex([bits][, uppercase]) returns the hexadecimal representation of the integer in the string, or a string not allocated if it is not an integer. A negative number is in two's complement on bits bits (default 64); the number is truncated to its lowest bits bits.