Табличный вывод в Фортране, который устойчив к неожиданным значениям? - PullRequest
2 голосов
/ 04 марта 2020

В Фортране можно ли печатать данные в табличной форме, не теряя информацию, когда требуется больше места, чем указано?

Например, рассмотрим программу

! format.f90
program main
  real(8) :: arr(5)
  arr = [0.0, 1.111, 22.22, 333.3, 444444444444444444.44]
  print '(F10.3)', arr
end program main

Тогда по умолчанию вывод для последней записи будет заменен звездочками, указывающими на недостаток места.

>> ifort format.f90 -o format.bin
>> ./format.bin
     0.000
     1.111
    22.220
   333.300
**********

Для сравнения, спецификаторы формата в стиле C автоматически увеличивают ширину столбца при необходимости, например,

// format.c
#include <stdio.h>
int main () {
  double arr[5] = {0.0, 1.111, 22.22, 333.3, 444444444444444444.44};
  for(int i=0; i<5; i++) {
    printf("%10.3f\n", arr[i]);
  }
}

>> gcc format.c -o format.bin
>> ./format.bin
     0.000
     1.111
    22.220
   333.300
444444444444444416.000

Возможно ли получить такое поведение в Fortran со встроенными функциями?

Опции, которые не удовлетворяют требованиям

G дескриптор. Дескриптор G позволяет надежно выводить данные в табличном хорошо читаемом формате и автоматически добавляет экспоненты при необходимости. Однако, это также тратит впустую пространство, если экспоненты не необходимы, и это не выравнивает запятую. Например, при переключении F10.3 на G11.4,"¶" (знак абзаца добавлен для выделения):

>> ifort format.f90 -o format.bin
>> ./format.bin
  0.000    ¶
  1.111    ¶
  22.22    ¶
  333.3    ¶
 0.4444E+18¶

Создание API форматирования на основе спецификатора F0. Спецификатор F0.3 допускает вывод переменной ширины, но не позволяет указывать минимальную ширину. Эту проблему можно решить, используя функцию-оболочку, похожую на leftpad , но встроенное или широко используемое решение будет предпочтительнее для большей вероятности фактического использования в базе кода. Как пример:

! format.f90
program main
  real(8) :: arr(5)
  integer :: i
  arr = [0.0, 1.111, 22.22, 333.3, 444444444444444444.44]

  ! more complicated print statement, because 'float2char'
  ! cannot be 'elemental' due to needing the 'alloctable' property.
  print '(A)', (float2char('(F0.3)', 10, arr(i)), i=1,5)

contains

  function float2char(format, width, value) result(r)
    character(:), allocatable :: r
    character(*), intent(in) :: format
    integer, intent(in) :: width
    real(8), intent(in) :: value

    character(64) :: buffer ! better: calculate size from value?

    write(buffer, format) value
    allocate(character(max(width, len_trim(buffer))) :: r)
    r(:) = trim(buffer)  ! (:) needed to prevent reallocation in recent compilers
    r(:) = adjustr(r)
  end function float2char

end program main

>> ifort format.f90 -o format.bin
>> ./format.bin
      .000
     1.111
    22.220
   333.300
444444452740661248.000

1 Ответ

3 голосов
/ 05 марта 2020

Да, поэтому в Фортране дескрипторы редактирования с фиксированной шириной действительно имеют ФИКСИРОВАННУЮ ширину. Иногда полезно, часто раздражает.

Одна вещь, которую вы можете сделать, это использовать дескриптор редактирования G, который похож на %g в C, а именно, что он переключается в научный формат c, когда число большое или маленькое. Это позволяет очень большим или маленьким значениям помещаться в поле фиксированной ширины. Однако обратите внимание, что при G редактировании d - это число значащих цифр, а не количество цифр после десятичной точки, как при F редактировании. Кроме того, он оставляет место в конце для показателя степени, даже если число находится в диапазоне, в котором показатель не требуется.

Ваш пример может выглядеть как


! format.f90
program main
  real(8) :: arr(4)
  arr = [0.0, 1.111, 222222222222.222, 3.333]
  print '(F10.3)', arr
  print *, 'With G edit'
  print '(G10.4)', arr
end program main

с выводом

     0.000
     1.111
**********
     3.333
 With G edit
 0.000    
 1.111    
0.2222E+12
 3.333    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...