Целочисленное форматирование вывода с оператором печати
Я заметил, что если я использую integer(16)
переменные, когда я использую print
, вывод содержит точное число ожидаемых пробелов. Таким образом, когда я использую (некоторые могут распознать проблему проекта Эйлера здесь)
implicit none
integer(16)::sum_sq,sq_sum,diff,i
sum_sq=0;sq_sum=0;
do i=1,100
sum_sq=sum_sq+i*i
sq_sum=sq_sum+i
enddo
diff=abs(sq_sum**2-sum_sq)
print *, "The difference is", diff
я получил
The difference is 25164150
в качестве вывода, но когда я использую integer(8)
или же integer
для переменных я получаю
The difference is 25164150
в качестве выхода. Это происходит с и без -m64
флаг и только на гфортран (мой ифорт вроде не принимает kind=16
, отдельная проблема, которая должна быть решена, но возвращает выходные данные с пробелами для integer(8)
).
Кто-нибудь знает, почему это происходит?
3 ответа
Как уже было сказано, вы используете IO, управляемый по спискам, что, хотя и удобно, но не полностью определяется стандартом языка. Таким образом, вы найдете идиосинкразии. Если вы хотите контролировать вывод, нужно будет использовать формат. Также удобен спецификатор формата "I0", который использует минимальное количество цифр, необходимое для вывода элемента.
В качестве дополнительной проблемы, "integer (N)" не обязательно будет N-байтовым целым числом. Это не то же самое, что "целое число *N", которое не является частью языкового стандарта. Многие компиляторы используют для значений типа количество байтов типа, но есть исключения. Оглядываясь назад, было ошибкой использовать целочисленные значения для обозначения целочисленных, реальных и логических подтипов. Если вы хотите выбирать типы по количеству байтов, существуют методы, начинающиеся с Fortran 2003. Модуль ISO_C_Binding в Fortran 2003 предоставляет указатели типов, такие как C_INT32_T, C_INT64_T и C_INT128_T. Модуль ISO_FORTRAN_ENV для Fortran 2008 предоставляет INT8, INT16, INT32 и INT64.
Это происходит потому, что вы используете форматирование по умолчанию для вывода.
print*
эквивалентно write(unit=*,fmt=*)
, где fmt=*
означает использовать форматирование по умолчанию для вывода, которое может зависеть от компилятора. Форматирование по умолчанию использует столько места, сколько, возможно, требуется для выводимого типа данных, без внесения изменений в зависимости от значения.
Рассмотрим следующий код:
integer(kind=4) :: a ! short integer for my compiler
integer(kind=8) :: b ! long integer for my compiler
a = 23
b = huge(a)
print*,a ! small value, short integer, we expect spaces
print*,huge(a) ! maximum value, short integer, we expect no spaces
print*,huge(b) ! maximum value, long integer, we expect no spaces
print*,b ! medium lenght value, long integer, we expect spaces
end
Когда компилятор с gfortran, вывод:
23
2147483647
9223372036854775807
2147483647
Первая строка - это небольшое число в 4-байтовом целочисленном представлении. Обратите внимание на места для заполнения до максимально возможного размера. Вторая строка - это наибольшее значение, которое может принимать 4-байтовое целое число. Хорошо вписывается в выходной, без пробелов. Третья строка является наибольшим значением 8-байтового целого числа. Плотно прилегает. Четвертая строка - это то же значение из 2-й строки, но в 8-байтовом целочисленном представлении. Обратите внимание на пробелы.
Это отвечает, почему вы получаете пробелы в выходных данных для форматирования по умолчанию. Он не совсем точно отвечает на ваш вопрос, поэтому в выходных данных нет пробелов для целого числа с четверной точностью. Я не знаю. Ни один из моих компиляторов (pgf90 10.6-0
, ifort 12.0.2.137
, gfortran 4.5.1
) поддерживает целочисленное значение. Может быть взломать компилятор. У кого-то может быть больше опыта с этой частью, и, надеюсь, они присоединятся.
Вывод, ориентированный на список, зависит от процессора (обратите внимание, что стандарт Fortran называет "процессор" тем, что мы обычно называем "компилятором"). Вот что говорит стандарт Fortran 90 о выводе по списку:
10.8.2 Список направленный вывод
...
Целочисленные выходные константы создаются с эффектом
Iw
редактировать дескрипторРеальные константы создаются с эффектом либо
F
редактировать дескриптор илиE
редактировать дескриптор, в зависимости от величиныx
значения и диапазона 10d1 <=x
<10 д2, гдеd1
а такжеd2
are processor-dependent integers. If the magnitudex
is within this range, the constant is produced using0PFw.d
; иначе,1PEw.dEe
используется.For numeric output, reasonable processor-dependent values of
w
,d
, а такжеe
are used for each of the numeric constants output.
(акцент мой)
The same rules are used for numerical values. The text in §10.10.4 of the Fortran 2008 standard copies that from the Fortran 90 standard so no changes in list-directed output were introduced.
As noted already by MSB, you can use the I0
edit descriptor to print integer values with the least amount of space necessary:
! Note the space in the string
PRINT '("The difference is ",I0)', diff