Оператор Fortran fomat с высочайшей точностью в системе

Кто-то, кто хочет меньшей точности, напишет

999    format ('The answer is x = ', F8.3)

Другие, которым нужна более высокая точность вывода, могут написать

999 format ('The answer is x = ', F18.12)

Таким образом, это полностью зависит от того, чего хочет пользователь. Какой оператор формата точно соответствует точности, используемой при расчете? (Обратите внимание, это может варьироваться от системы к системе)


person Jagte    schedule 26.04.2013    source источник
comment
Список операций ввода-вывода, write (*, *), должен автоматически обеспечивать точность типов в списке. Но вы отказываетесь от контроля над макетом вывода. Есть ли гарантия, что значения могут быть считаны обратно с точным восстановлением значений??   -  person M. S. B.    schedule 26.04.2013
comment
без сомнения, вещь, зависящая от компилятора, но запись, направленная по списку, дает мне немного меньшую точность, чем требуется для чтения значения без потерь (похоже, * дает f15.6 для значения с одинарной точностью порядка 1, где требуется f15.7 . )   -  person agentp    schedule 26.04.2013
comment
@Jagte К вашему сведению, заполнение строки в формате statent - это старая школа. Я надеюсь, вы не думаете, что это необходимо. write(*,*) 'Ответ есть', x, вероятно, все, что вам нужно, если только вы действительно не хотите помнить о возможной потере точности в одну цифру или вам действительно нужен точный контроль над интервалом.   -  person agentp    schedule 26.04.2013
comment
Как можно определить, какая точность использовалась при расчете?   -  person pattivacek    schedule 05.09.2013


Ответы (2)


Это сложный вопрос, потому что вы требуете «точности расчета», которая зависит от очень многих факторов. Например: если я решу f(x)=0 с помощью метода Ньютона с допуском 1E-6, нужен ли вам формат с семью цифрами?

С другой стороны, если вы имеете в виду «самую высокую точность, достижимую для типа» (например, двойную или одинарную точность), вы можете просто найти соответствующий эпсилон (машинный eps или точность) и использовать его как флаг формата. Если эпсилон равен 1E-15, вы можете использовать флаг формата, который не может содержать более 16 цифр.

В Фортране вы можете использовать функцию EPSILON(X), чтобы получить это число (ответ будет зависеть от типа X), вы можете взять пол абсолютного значения логарифма (по основанию 10) эпсилон и сделать это количество десятичных знаков в вашем представлении с плавающей запятой.

Например, если эпсилон равен 1E-12, логарифм равен -12, абс равен 12, а пол равен 12, поэтому вам нужен формат вроде 15.12F (12 десятичных знаков + 1 точка + ноль + знак = 15 знаков). )

person Escualo    schedule 26.04.2013
comment
Чтобы сделать это автоматически, вы можете WRITE число, полученное из EPSILON(), преобразовать в символ, а затем соединить его с оператором формата. - person Yossarian; 26.04.2013
comment
@Arrieta, вы на полпути ... как только вы определите требуемую точность, вам также нужно учитывать величину числа, чтобы получить точно необходимое количество десятичных знаков. Много работы, чтобы заново изобрести ориентированное на список форматирование. - person agentp; 26.04.2013
comment
@George: Я согласен с вами ... На самом деле мне не нравится мой ответ ;( Я предлагаю хак, который идет на полпути. Но у меня нет больше идей ;( - person Escualo; 26.04.2013

Проблема с числами с плавающей запятой заключается в том, что нет точности как таковой: только значащие цифры.

Например, если вы вычисляете долготу в реальном * 1, недалеко от Великобритании, вы будете иметь точность до 6 знаков после запятой, но если вы находитесь в Колорадо-Спрингс, то точность будет только до 4 знаков после запятой. Не имеет смысла печатать число в формате F, это просто мусор после 4-го знака после запятой.

Если вы хотите печатать с максимальной точностью, печатайте в формате E. Поскольку это всегда n.nn..nEnn, вы получаете все значащие цифры.

Изменить – запрос пользователя 4050 Попробуйте следующий пример.

program main
   real intpart, multiplier
   integer ii

   multiplier = 1
   do ii = 1, 6
      intpart = 9.87654321
      intpart = intpart * multiplier
      print '(F15.7 E15.7 G15.8)', intpart, intpart, intpart
      multiplier = multiplier * 10
   end do
   stop
end program

То, что вы получите, это что-то вроде

      9.8765430  0.9876543E+01  9.8765430
     98.7654266  0.9876543E+02  98.765427
    987.6542969  0.9876543E+03  987.65430
   9876.5429688  0.9876543E+04  9876.5430 
  98765.4296875  0.9876543E+05  98765.430
 987654.3125000  0.9876543E+06  987654.31

Обратите внимание, что точность изменяется по мере увеличения числа, потому что число с плавающей запятой имеет только 7 значащих цифр.

person cup    schedule 26.04.2013
comment
Когда этот ответ понятен, он неверен. Хорошим рабочим определением точности числа, хранимого или обрабатываемого компьютером, является количество значащих цифр, сохраняемых или обрабатываемых. Дескриптор редактирования e Фортрана может использоваться для записи ни одного, нескольких, многих или всех значащих цифр real. Что касается комментария об относительной точности долготы в Великобритании по сравнению с Колорадо, я полагаю, вы застряли, думая в градусах - измените на радианы. - person High Performance Mark; 26.04.2013
comment
Когда большинство людей, использующих Fortran, говорят о точности, они имеют в виду десятичные разряды. Дело в том, чтобы использовать формат E, а не формат F, чтобы получить значащие цифры. Если используется формат F, вы можете получить все значащие цифры, недостаточные цифры или получить абсолютный мусор. Долготы — это просто пример, который всем понятен: это может быть что угодно с широким диапазоном. - person cup; 27.04.2013
comment
@cup Меня интересует ваш ответ, но я не вижу, чем он отличается от использования формата F, вам все равно нужно указать количество цифр, которые вы хотите напечатать также в формате E, нет? - person Herman Toothrot; 05.09.2016