2013-09-21 3 views
1

Я решил изучить язык fortran95 (причина, почему это не важно). Однако, будучи новичком, я столкнулся с странной проблемой, которую я действительно не могу объяснить, поэтому мне нужна помощь.fortran 95 округление на своем собственном

У меня есть алгоритм вставки сортировки:

subroutine insertion_sort_REAL4(array, array_len) 
    implicit none 
!parameners 
    integer :: array_len 
    real (kind=4), dimension(array_len) :: array 
!variables 
    integer :: i,key,hole_pos 
    do i = 0,array_len 
     key = array(i) 
     hole_pos = i; 
     do while ((hole_pos > 0.0) .and. (key < array(hole_pos - 1))) 
     array(hole_pos) = array(hole_pos - 1) 
     hole_pos = hole_pos - 1 
     end do 
     array(hole_pos) = key 
    end do 
    return 
end 

И есть основная программа (выдержка):

real (kind = 4), dimension(3) :: x 
x(1) = 3.1 
x(2) = 4.3 
x(3) = 5.4 
write(*,*) 'Array = ',x 
call insertion_sort_REAL4(x,3) 
write(*,*) 'Array = ',x 

Первые write заявление распечатывает

Array = 3.09999990  4.30000019  5.40000010 

Почему цифры немного изменились? По умолчанию fortran95 не использует стандарт IEEE754?

Но скажем, я могу жить с небольшими изменениями; вторые write заявления распечатывает

Array = 3.00000000  4.00000000  5.00000000 

Почему цифры округлены до? Это действительно раздражает меня, и форматирование заявления «писать» не приносит пользы, и поиски Google не помогли. Я предполагаю, что в интернете не так много вещей о fortran, как о C. Я - достойный программист на C, поэтому любые параллели с ним оцениваются. Спасибо вам за помощь!

+0

Это то время дня снова. Обязательная ссылка: [Что каждый компьютерный ученый должен знать о арифметике с плавающей точкой] (http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html) – ppeterka

+0

в этом случае, однако он не делает любая плавающая арифметика. Значения будут точно сохранены (если бы не для непреднамеренного преобразования типа.) – agentp

ответ

3

Десятичное число, такое как «3.1», скорее всего, не будет иметь точного представления в двоичном числе конечной длины. Оператор исходного кода x(1) = 3.1 заставляет компьютер преобразовывать это десятичное число в двоичное и хранить его. Заявление write (*, *) x(1) заставляет компьютер извлекать это двоичное значение и преобразовывать его в десятичный. Поскольку «3.1» не может быть точно представлено в двоичной форме с конечной длиной, преобразование в десятичную строку точно не восстанавливает «3.1». Это объясняет вывод «3.09999990». Это не специфичная для Fortran, но общая арифметика с плавающей запятой с конечной точностью.

Что касается другой проблемы, то key объявляется целочисленным в подпрограмме сортировки и, таким образом, округляет числа до целых чисел. Когда я скомпилировал вашу программу с полными предупреждениями о компиляторе, gfortran уведомил меня об этом.

Если вы gfortran, попробуйте следующие параметры компилятора: -O2 -fimplicit-none -Wall -Wline-truncation -Wcharacter-truncation -Wsurprising -Waliasing -Wimplicit-interface -Wunused-parameter -fwhole-file -fcheck=all -std=f2008 -pedantic -fbacktrace. Вы также обнаружите, что ваша программа имеет индексную ошибку.

+1

AH да! Спасибо! проблема с целочисленной переменной «ключ» -> Я думаю, что компилятор делает неявное преобразование без уведомления. Btw: Что такое ошибка индекса? Программа компилируется и работает нормально ... – Andro

+1

Ошибка индексации, когда программа ссылается на элемент массива, который не существует. Например, для 'array (1: 3)', обращение к 'array (0)' будет ошибкой. Если вы изучите свою программу, вы найдете такую ​​проблему. Или используйте опцию для проверки индекса времени выполнения вашего компилятора - этот параметр является одним из преимуществ Fortran по сравнению с некоторыми другими скомпилированными языками. –

+0

yes fortran делает неявное преобразование типа, такое же, как C .. – agentp

1

Для первая часть: он использует IEEE754, и именно поэтому цифры «изменены».

What Every Computer Scientist Should Know About Floating-Point Arithmetic статья должна читать, чтобы понять, как это работает, и есть хорошие IEEE754 calculators тоже ...

Так 3,1 никогда не был точно 3,1, но

3.0999999046325684 

в первую очередь.

Что касается второй части: они не округляются до но преобразуются в целые числа, но я не в Fortran, так что я думаю, что-то объявлено как междунар в insertion_sort_REAL4 рутины, что приводит число к преобразуются в целые числа.

+0

Да, это было так. Спасибо за ваш ответ и ссылку. Я должен это прочитать. – Andro

+0

@ Andrej ах, я вижу, что M.S.Bs ответ сейчас, это объясняет все. Статья является настоящим открытием. – ppeterka

Смежные вопросы