내장 함수 'CEILING'을 사용하려고하지만 반올림 오류로 인해 때때로 원하는 것을 얻지 못합니다.반올림 오류의 영향을받지 않고 CEILING 사용
PROGRAM MAIN
IMPLICIT NONE
INTEGER, PARAMETER :: ppm_kind_double = KIND(1.0D0)
REAL(ppm_kind_double) :: before,after,dx
before = -0.112
dx = 0.008
after = CEILING(before/dx)
WRITE(*,*) before, dx, before/dx, after
END
코드의 난 '이전'에주는 가치와 'DX는 그냥 데모입니다. 예를 들어/dx = -13.5 이전의 경우, CEILING을 사용하여 -13을 얻고 싶습니다. 그러나 제가 보여 주었던 그림을 보려면 실제로 -14를 얻고 싶습니다.
IF(ABS(NINT(before/dx) - before/dx) < 0.001)
과 같은 몇 가지 인수를 사용해 보았습니다. 그러나 그것은 단순히 아름답 지 않습니다. 이 작업을 수행하는 더 좋은 방법이 있습니까?
업데이트 : 내가 ppm_kind_double의 상수 변수를 설정하면 문제가 발생하지 않는 것을 발견 놀랐습니다
. 그래서이 '반올림 오류'는 내가 사용하는 기계의 반올림 정확도에 대한 자릿수가 ppm_kind_double에 정의 된 것 이상일 때만 발생합니다. 실제로 클러스터의 프로그램 (이 데모 코드 아님)을 실행합니다.이 코드는 기계 정밀도에 대해 알지 못합니다. 문제를 일으키는 기계의 4 배 정밀도일까요? 반올림 오류가 어디에서 오는지 당신이 알고하지 않기 때문에이 조금 까다 롭습니다
before = -0.112_ppm_kind_double
dx = 0.008_ppm_kind_double
너는 나에게 -14를 원하고 조금 벗어 던졌다. -0.112/0.008이 정확히 -14라는 것을 깨닫는 데는 시간이 걸렸지 만 반올림 오류 때문에 결과가 약간 더 많아지고 'CEILING'은이 작은 오류를 증폭시킵니다. – chw21
@ chw21, 실제로 나는 당신의 이전 코멘트를보고 당신이 그것을 찾을 때까지 기다리고있었습니다. :) – Ruizhi
주어진 정밀도가 여기에있는 문제의 일부인 경우 리터럴 상수가 단 정밀도 만 사용한다는 점에 유의해야합니다. '-0.112'는 아마도'-0.112_ppm_kind_double'이라고 써야합니다. 이 변경으로 인해 근본적인 문제는 해결되지 않습니다. – IanH