有哪些方法可以找到包含特定实数值的数组元素?
What methods are there for finding the element of an array containing a specific real value?
在 Fortran 代码中,我有一个数组 a
,其值统一从 0.0
到 1.2
,我正在寻找最接近 1.0
。
在 Fortran 中似乎没有任何内在函数可以做到这一点,所以我用 MINLOC 做了一个 hacky 解决方法:(注意 temp
与 a
的形状相同)
do i=1,n
temp(i) = 1.0 - a(i)
end do
loc = 0 !note that loc is an integer array, declared as 'loc(1)'
index_1 = minloc(abs(temp(:))) !this is the index of a closest to 1.0
这似乎可以解决问题。
我对实现此目的的其他方法很感兴趣,所以有几个问题:
- MINLOC 是如何工作的?
- 是否有其他例程可以直接到达那里(即无需制作第二个阵列)?
- 这在其他语言中是如何处理的?
谢谢。
编辑:我之前链接到 this article,将其作为寻找 MINLOC
替代方案的部分动机,但已将其删除,因为一些评论者指出它有些无关紧要。包括它似乎有损于我的目标,即找到该方法的替代方法。
首先请注意,链接的文章并没有批评 MINLOC
本身的性能,而是批评了寻找特定值的性能。
在 Fortran 2008 中有内在的 FINDLOC
用于这个确切的目的,但它可能不是解决问题的正确方法。但是,对于所引用文章中的问题,这将是正确的做法。另见 Fortran findloc intrinsic
速度缓慢的一个原因(立即可见)是调用 MINLOC(abs(temp(:)))
时必须为 abs(temp(:))
创建一个临时数组。另一个原因是当找到匹配项时,文章中的循环可以立即退出。然而,这对您的申请并不重要。
内在的 MINLOC
本身可能并不慢,它只是在一个简单的循环中搜索数组。
这些结果也会因编译器而异。您检查过编译器的性能差异了吗?
最后的建议:只写一个避免临时数组的简单循环。
用于查找最接近的浮点元素的简单循环。简单的 CS101 内容。
min_diff = huge(1.0)
idx = 0
do i = 1, size(a)
diff = abs(a(i)-to_find)
if ( diff < min_diff) then
idx = i
min_diff = diff
end if
end do
这不会 运行 比您的解决方案更快,但它肯定会缩短代码:
index_1 = minloc(abs(a - 1))
虽然您不必以这种方式自己设置临时数组,但编译器仍会在幕后进行设置。 MINLOC 靠蛮力工作:找到最小值没有捷径。
如果需要在这个数组中反复查找不同的值,先对数组a
进行排序,然后进行二分查找会快很多。这会将 运行 时间从 O(n) 减少到 O(log(n)),其中 n 是 a
.
的大小
在 Fortran 代码中,我有一个数组 a
,其值统一从 0.0
到 1.2
,我正在寻找最接近 1.0
。
在 Fortran 中似乎没有任何内在函数可以做到这一点,所以我用 MINLOC 做了一个 hacky 解决方法:(注意 temp
与 a
的形状相同)
do i=1,n
temp(i) = 1.0 - a(i)
end do
loc = 0 !note that loc is an integer array, declared as 'loc(1)'
index_1 = minloc(abs(temp(:))) !this is the index of a closest to 1.0
这似乎可以解决问题。
我对实现此目的的其他方法很感兴趣,所以有几个问题:
- MINLOC 是如何工作的?
- 是否有其他例程可以直接到达那里(即无需制作第二个阵列)?
- 这在其他语言中是如何处理的?
谢谢。
编辑:我之前链接到 this article,将其作为寻找 MINLOC
替代方案的部分动机,但已将其删除,因为一些评论者指出它有些无关紧要。包括它似乎有损于我的目标,即找到该方法的替代方法。
首先请注意,链接的文章并没有批评 MINLOC
本身的性能,而是批评了寻找特定值的性能。
在 Fortran 2008 中有内在的 FINDLOC
用于这个确切的目的,但它可能不是解决问题的正确方法。但是,对于所引用文章中的问题,这将是正确的做法。另见 Fortran findloc intrinsic
速度缓慢的一个原因(立即可见)是调用 MINLOC(abs(temp(:)))
时必须为 abs(temp(:))
创建一个临时数组。另一个原因是当找到匹配项时,文章中的循环可以立即退出。然而,这对您的申请并不重要。
内在的 MINLOC
本身可能并不慢,它只是在一个简单的循环中搜索数组。
这些结果也会因编译器而异。您检查过编译器的性能差异了吗?
最后的建议:只写一个避免临时数组的简单循环。
用于查找最接近的浮点元素的简单循环。简单的 CS101 内容。
min_diff = huge(1.0)
idx = 0
do i = 1, size(a)
diff = abs(a(i)-to_find)
if ( diff < min_diff) then
idx = i
min_diff = diff
end if
end do
这不会 运行 比您的解决方案更快,但它肯定会缩短代码:
index_1 = minloc(abs(a - 1))
虽然您不必以这种方式自己设置临时数组,但编译器仍会在幕后进行设置。 MINLOC 靠蛮力工作:找到最小值没有捷径。
如果需要在这个数组中反复查找不同的值,先对数组a
进行排序,然后进行二分查找会快很多。这会将 运行 时间从 O(n) 减少到 O(log(n)),其中 n 是 a
.