От новичка до гуру: Курсы программирования на CyberDuff

Табличный вывод на Фортране, устойчивый к неожиданным значениям?

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

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

! 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

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

Варианты, которые не соответствуют требованиям

Дескриптор 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
04.03.2020

  • Почему F0.3 не является встроенной функцией? Это совершенно стандартный Фортран. 04.03.2020
  • @IanBush F0.3 встроен, но сам по себе не предоставляет табличный вывод. F10.3 обеспечивает табличный вывод, но совершенно бесполезен, если данные не помещаются в 10 столбцов. Для сравнения, printf встроено в C и обеспечивает табличный вывод, автоматически ослабляя табличное свойство, если данные не подходят. F0.3 можно использовать для создания функции или подпрограммы, которая обеспечивает форматированное представление из 10 или более символов. 05.03.2020

Ответы:


1

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

Одна вещь, которую вы можете сделать, это использовать дескриптор редактирования G, который похож на %g в 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    
05.03.2020
  • Это может быть полезно, но в большинстве случаев не обеспечивает табличный вывод. Например, если с F10.3 число 222.2 будет напечатано как ␣␣␣222.200, с G10.4 оно будет напечатано как ␣␣␣␣␣␣222.2, а 1.111 будет напечатано как ␣␣␣␣␣␣1.111, так что запятая не будет выровнена по одному и тому же столбцу. 06.03.2020
  • Новые материалы

    Прогрессивная транспиляция
    В последние годы программисты JavaScript (он же EcmaScript) часто используют компиляторы исходного кода , также известные как транспиляторы , для преобразования более усовершенствованной или..

    Алиса в стране машинного обучения — инициатива «100 дней кода машинного обучения»
    Covnets, регрессия, классификация, ReLU, предвзятость… — все это интригующие жаргоны, которые я слышал от своих сверстников, выбравших курс машинного обучения, по касательной во время обычного..

    Иногда учитель, всегда ученик
    Учение Йоды в применении к развитию разработчиков «Делай или не делай. Нет никакой попытки.” Обучение программированию превратилось в современное «создание группы» или «написание книги»...

    Как создать файл конфигурации сборки в Xcode | Серия настроек проекта Xcode
    Эта статья шаг за шагом расскажет вам, как создать новый файл конфигурации сборки в вашем проекте Xcode. Что такое файл конфигурации сборки? Файл конфигурации сборки — это обычный..

    Venv против Virtualenv в Python  — что использовать?
    Когда дело доходит до создания виртуальных сред в Python, есть два популярных варианта: venv и virtualenv. Оба инструмента служат одной цели — созданию изолированных сред для ваших проектов..

    Реализация персептрона на Python (для абсолютных новичков)
    Введение За последние пару десятилетий было довольно много шумихи вокруг искусственного интеллекта и его приложений. В этой статье мы обсудим, что такое искусственный интеллект и его основное..

    С помощью javascript мы можем сделать это в одну строку.
    С помощью javascript мы можем сделать это в одну строку. let x = 5; let y = 7; y = [x, x = y][0]; Но то, что мы можем , не обязательно означает, что мы должны это делать.