我正在尝试使用内在函数'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
我在代码中给'before'和'dx'的值仅用于演示。例如,对于/ dx = -13.5之前的那些,我想使用CEILING来获得-13。但是对于我展示的图片,我实际上想得到-14。我考虑过使用像
这样的论点 IF(ABS(NINT(before/dx) - before/dx) < 0.001)
但那并不美丽。有没有更好的方法来做到这一点?
更新
我很惊讶地发现,如果我将变量设置为ppm_kind_double中的常量,则不会出现问题。所以我猜这个'舍入错误'只会在我使用的机器的舍入精度的位数大于ppm_kind_double中定义的位数时发生。我实际上在一个集群上运行我的程序(不是这个演示代码),我不知道它的机器精度。那么也许这台机器的四倍精度会导致问题呢?
将常量设置为双精度后:
before = -0.112_ppm_kind_double
dx = 0.008_ppm_kind_double
答案 0 :(得分:0)
这有点棘手,因为你永远不知道舍入误差来自何处。如果dx
只比0.008
稍微大一点,则除法before/dx
可能仍会四舍五入到相同的值,但现在-13
将是正确答案。
那就是说,我所看到的最常见的方法就是将之前的值轻微推向。像这样:
program sign_test
use iso_fortran_env
implicit none
real(kind=real64) :: a, b
integer(kind=int32) :: c
a = -0.112
b = 0.008
c = my_ceiling(a/b)
print*, a, b, c
contains
function my_ceiling(v)
implicit none
real(kind=real64), intent(in) :: v
integer(kind=int32) :: my_ceiling
my_ceiling = ceiling(v - 1d-6, kind=int32)
end function my_ceiling
end program sign_test
这对绝大多数价值观都没有任何影响,但现在有一些价值会超出预期。
答案 1 :(得分:0)
请注意,如果您的实际意义上是&#34;确切的&#34;要达到指定的精度,您可以执行以下操作:
public boolean isObjectStillValid(Object source, HttpHeaders headers) {
Assert.notNull(source, "Source object must not be null!");
Assert.notNull(headers, "HttpHeaders must not be null!");
if (headers.getIfModifiedSince() == -1) {
return false;
}
//THE WRAPPER IS NULL IF NO AUDITING ANNOTATIONS PRESENT
AuditableBeanWrapper wrapper = auditableBeanWrapperFactory.getBeanWrapperFor(source);
long current = wrapper.getLastModifiedDate().getTimeInMillis() / 1000 * 1000;
return current <= headers.getIfModifiedSince();
}
这适用于您的示例..您还没有说出您对这两个值的正面评价等等,因此您可能需要稍微努力。