Фортран установил NaN на нуль [дубликат]

Вот мое (не самое результативное) решение. Он полагается на то, что преобразование байт / латин-1 без потерь, что не истинно для преобразований байтов / ASCII или байтов / UTF8.

Преимущества в том, что It Works ( tm) для любых байтовых значений (некоторые другие решения работают некорректно с байтами 0x80-0xff) и могут быть расширены для выполнения более расширенного соответствия регулярных выражений.

using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;

class C {

  public static void Main() {
    byte[] data = {0, 100, 0, 255, 100, 0, 100, 0, 255};
    byte[] pattern = {0, 255};
    foreach (int i in FindAll(data, pattern)) {
      Console.WriteLine(i);
    }
  }

  public static IEnumerable<int> FindAll(
    byte[] haystack,
    byte[] needle
  ) {
    // bytes <-> latin-1 conversion is lossless
    Encoding latin1 = Encoding.GetEncoding("iso-8859-1");
    string sHaystack = latin1.GetString(haystack);
    string sNeedle = latin1.GetString(needle);
    for (Match m = Regex.Match(sHaystack, Regex.Escape(sNeedle));
         m.Success; m = m.NextMatch()) {
      yield return m.Index;
    }
  }
}
18
задан Vladimir F 23 May 2016 в 16:32
поделиться

6 ответов

Простым способом без использования ieee_arithmatic является выполнение следующих действий.

Бесконечность: Определите свою переменную infinity = HUGE(dbl_prec_var) (или, если она у вас есть, переменная точности четности). Затем вы можете просто проверить, не изменилась ли ваша переменная на if(my_var > infinity).

NAN: Это еще проще. По определению, NAN не равна ничему, даже самому себе. Просто сравните переменную с самим собой: if(my_var /= my_var).

19
ответ дан Kyle Kanos 17 August 2018 в 19:25
поделиться
  • 1
    Странно, что никто не упомянул дело NaN. Думаю, они были обеспокоены тем, что вы можете использовать fortran на процессоре non-ieee? Помимо этого, проверка NaN очень надежна. С другой стороны, проверка бесконечности немного менее изящна, так как она зависит от типа данных. – amaurea 30 June 2013 в 21:49
  • 2
    Остерегайтесь умных оптимизаторов. – IanH 30 June 2013 в 21:59
  • 3
    @amaurea: вы можете позаботиться о проблеме с типом данных, используя INTERFACE и связав несколько типов, которые вы могли бы использовать, в том же MODULE PROCEDURE. – Kyle Kanos 30 June 2013 в 23:06
  • 4
    @IanH: Вы могли бы разумно установить infinity = 1.e100_dp и все равно получить хороший инструмент проверки бесконечности. Даже при использовании небольших весов (например, 1е-24 м) для описания больших масштабов (например, 1е + 24 м) вы все еще не находите места около 1э100. – Kyle Kanos 30 June 2013 в 23:08
  • 5
    Оптимизатор действительно оптимизирует проверку, если запрашивается fast_math или подобное. Увы, он даже оптимизирует встроенный gfortran isnan. Ответственность программиста - это заботиться об этом, когда он запрашивает небезопасную быструю математику и все еще хочет обнаружить NaN. – Vladimir F 23 May 2016 в 15:48

У меня недостаточно комментариев для комментариев, поэтому я буду «отвечать» на предложение Рика Томпсона для тестирования бесконечности.

if (A-1 .eq. A) 

Это также верно, если A - очень большое число с плавающей запятой, а 1 ниже точности A.

Простой тест:

subroutine test_inf_1(A)
    real, intent(in) :: A
    print*, "Test (A-1 == A)"
    if (A-1 .eq. A) then
        print*, "    INFINITY!!!"
    else
        print*, "    NOT infinite"
    endif
end subroutine

subroutine test_inf_2(A)
    real, intent(in) :: A
    print*, "Test (A > HUGE(A))"
    if (A > HUGE(A)) then
        print*, "    INFINITY!!!"
    else
        print*, "    NOT infinite"
    endif
end subroutine


program test
    real :: A,B

    A=10
    print*, "A = ",A
    call test_inf_1(A)
    call test_inf_2(A)
    print*, ""

    A=1e20
    print*, "A = ",A
    call test_inf_1(A)
    call test_inf_2(A)
    print*, ""

    B=0.0 ! B is necessary to trick gfortran into compiling this
    A=1/B
    print*, "A = ",A
    call test_inf_1(A)
    call test_inf_2(A)
    print*, ""

end program test

выходов:

A =    10.0000000    
Test (A-1 == A)
    NOT infinite
Test (A > HUGE(A))
    NOT infinite

A =    1.00000002E+20
Test (A-1 == A)
    INFINITY!!!
Test (A > HUGE(A))
    NOT infinite

A =          Infinity
Test (A-1 == A)
    INFINITY!!!
Test (A > HUGE(A))
    INFINITY!!!
3
ответ дан Ethan Gutmann 17 August 2018 в 19:25
поделиться

Нет.

Также не существует стандартного метода проверки бесконечности или NaN в Fortran 90/95, а также не может быть стандартного. Не существует стандартного метода определения любого из этих квазицифровых чисел в Fortran 90/95.

0
ответ дан High Performance Mark 17 August 2018 в 19:25
поделиться
  • 1
    Ну, в рамках стандарта IEEE Floating Point, то есть. – astrojuanlu 1 July 2013 в 10:51

Нет.

Явные части IEEE_ARITHMETIC для генерации / проверки для NaN достаточно просты для записи для gfortran для конкретной архитектуры.

2
ответ дан IanH 17 August 2018 в 19:25
поделиться
  • 1
    Что касается вашего второго заявления, они, похоже, не согласны с gcc.gnu.org/ml/gcc-bugs/2012-10/msg00580.html или я что-то упускаю? – astrojuanlu 30 June 2013 в 12:54
  • 2
    Btw Я добавил ссылку на соответствующую ошибку gfortran (которая датируется 2006 годом и имеет статус NEW). – astrojuanlu 30 June 2013 в 12:59
  • 3
    Написание all IEEE_ARITHMETIC для всех архитектур, которые поддерживает gfortran, с чем связана эта ошибка, было бы сложно! Написание выбранных битов, которые генерируют / проверяют для NaN, на определенной архитектуре (например, x64) довольно легко. См. sites.google.com/site/tprincesite/Home/gfortran-ieee-arithmetic в качестве примера Тимом Принцем, который полагается на неравенство любых двух NaN, альтернативный подход - использовать бит Fortran чтобы генерировать / тестировать конкретные шаблоны, указывающие NaN. (Подробнее см. «Оригинальная ошибка gfortran 29383»). – IanH 30 June 2013 в 14:18

Я использовал:

  PROGRAM MYTEST
  USE, INTRINSIC :: IEEE_ARITHMETIC, ONLY: IEEE_IS_FINITE      
  DOUBLE PRECISION :: number, test
  number = 'the expression to test'
  test = number/number
  IF (IEEE_IS_FINITE(test)) THEN
     WRITE(*,*) 'We are OK'
  ELSE
     WRITE(*,*) 'Got a problem'
  END IF         
     WRITE(*,*) number, test
  END PROGRAM MYTEST

Это напечатает сообщение «Получил проблему» для числа = 0.0D0, 1.0D0 / 0.0D0, 0.0D0 / 0.0D0, SQRT (-2.0D0), а также для переполнений и недочетов, таких как number = EXP (1.0D800) или number = EXP (-1.0D800). Обратите внимание, что в целом такие вещи, как number = EXP (1.0D-800), просто устанавливают число = 1.0 и выдают предупреждение во время компиляции, но программа будет печатать «Мы в порядке», что я считаю приемлемым.

ПР.

1
ответ дан Otto Linsuain 17 August 2018 в 19:25
поделиться
  • 1
    В вопросе задается номер NotManumber, но ваш пример показывает конечность. Он также поймает + Inf и -Inf как ложные срабатывания. Также обратите внимание, что вопрос действительно интересовался тем, что делать, когда IEEE_ARITHMETIC недоступен и спрашивает, как это сделать с помощью Fortran 90/95. – Vladimir F 23 May 2016 в 15:41
  • 2
    В дополнение к опасениям Владимира Ф нет никакой гарантии, что даже с ieee_arithmetic, что ieee_support_datatype(test) истинно. Если это не так, считать ieee_is_finite(test) не разрешено. – francescalus 23 May 2016 в 16:15
  • 3
    Я был слишком суровым, вопрос также требует эквивалента IEEE_IS_FINITE(). Но дело в том, что ОП знает, что он существует, но просит альтернативы. – Vladimir F 23 May 2016 в 16:33

Для Inf, похоже, работает, что если (A-1. Aq. A) истинно, то A является Inf

-2
ответ дан Rick Thompson 17 August 2018 в 19:25
поделиться
  • 1
    Может быть, вы захотите немного подробнее остановиться. – CinCout 12 November 2014 в 16:53
Другие вопросы по тегам:

Похожие вопросы: