C++ 在一个数组中查找具有最小绝对值的元素
我试图在一个数组中找到一个元素,它的绝对值最小。例如,在数组[5.1,-2.2,8.2,-1,4,3,-5,6]中,我希望得到值-1。我使用以下代码(myarray是1D数组,未排序)C++ 在一个数组中查找具有最小绝对值的元素,c++,C++,我试图在一个数组中找到一个元素,它的绝对值最小。例如,在数组[5.1,-2.2,8.2,-1,4,3,-5,6]中,我希望得到值-1。我使用以下代码(myarray是1D数组,未排序) for(int i=1;i STD::Abjess(代码>,因为我的理解可以推断数据类型,因为在C++中你可以使用模板等。 如果你不想用晶圆厂显然是这样的电话 float myAbs(const float val) { return (val<0) ? -val : val; } float my
for(int i=1;i<8;++i)
{
如果(fabsf(myarray[i])让我给出一些有帮助的想法:
float minVal = fabsf(myarray[0]);
for (int i = 1; i < 8; ++i)
{
if(fabsf(myarray[i])<minVal) minVal = fabsf(myarray[i]);
}
myarray[0] = minVal;
使用这种方法,通过插入数字,它们已按升序排序。较小的比较器通常是std::set的一个集合,但您可以将其更改为使用与本例中不同的内容。这可能对较大的数据集有所帮助,但您提到您只有八个值要比较,因此它确实没有帮助
八个元素是一个非常小的数字,它可能与std::array myarray
的声明一起放在堆栈中,靠近排序函数,然后再填充数据。您应该在完整的代码集上添加这些变量,并观察有什么帮助。当然,如果您声明std::array myarray
或float[8]myarray
运行时您应该会得到相同的结果
<>你可以检查的是,如果代码< FabsF真的使用浮点作为参数,并且不将变量转换为双,这会降低性能。还有代码> STD::Abjess(<)>代码>,因为我的理解可以推断数据类型,因为在C++中你可以使用模板等。
如果你不想用晶圆厂显然是这样的电话
float myAbs(const float val)
{
return (val<0) ? -val : val;
}
float myAbs(常量float val)
{
return(val有一些城市神话,比如内联、手工展开循环以及类似的神话,它们应该可以让你的代码更快。好消息是你不必这么做,至少如果你使用-O3编译器优化的话
坏消息是,如果您已经使用了-O3,那么您无法加快此函数的速度:编译器将优化您的代码!例如,它肯定会按照一些建议对fabsf(myarray[0])
进行缓存。使用此“重构”可以实现的唯一功能就是将bug构建到程序中,使其可读性降低
我的建议是到其他地方寻求改进:
尝试减少此代码的调用次数
如果这段代码是一个瓶颈,那么我的猜测是您会一次又一次地重新计算最小值(否则将值填充到数组中大约需要相同的时间),因此缓存搜索结果
将成本转移到更改数组的元素上,例如使用一些奇特的数据结构(堆、优先级队列)或跟踪元素的最小值。假设您的数组只有两个元素值[1,2]
,那么最小值是1
。现在如果您更改
- 2到3,你什么都不用做
- 2到0,您可以轻松地将最小值更新为
0
- 从1到3,你必须循环所有的元素,但这种情况可能并不常见
你能预先存储这些值吗
正如@Gerstrong所提到的,将数字存储在循环之外,并且只在阵列发生变化时计算它,这将给您带来提升
调用或只能对数组进行排序,以便正确的值位于正确的位置
std::nth_element(v.begin(), v.begin(), v.end(), [](float& lhs, float& rhs){
return fabsf(lhs)<fabsf(rhs);
});
std::n_元素(v.begin(),v.begin(),v.end(),[](浮点和左半球,浮点和右半球){
return fabsf(lhs)一个想法是以“锦标赛”的方式进行比较,而不是线性比较。换句话说,首先比较1与2,3与4,以此类推。然后取这4个元素并执行相同的操作,然后再次进行比较,直到只剩下一个元素
这不会更改比较的数量。由于每次比较都会从运行中删除一个元素,因此无论发生什么情况,您都将有7个比较。因此,我为什么建议这样做?因为它会从代码中删除数据依赖项。现代处理器有多个管道,可以同时停用多条指令。但是,在循环中进行比较时,每个循环迭代都取决于前一个循环。在以锦标赛方式进行比较时,前四个比较是完全独立的,因此处理器可以同时进行所有比较
除此之外,您还可以在一个简单的循环中同时计算所有晶圆厂,并将其放入一个新数组中。由于晶圆厂的计算是独立的,因此可以很容易地加快速度。您可以先进行此操作,然后进行锦标赛式的比较以获得索引。操作数应该完全相同,只是在变化调整顺序,以便编译器可以更容易地看到缺少数据依赖关系的较大块
具有最小绝对值的数组元素
让数组,A
A = [5.1, -2.2, 8.2, -1, 4, 3, -5, 6]
A
的最小绝对值为
double miniAbsValue = A.array().abs().minCoeff();
int i_minimum = 0; // to find the position of minimum absolute value
for(int i = 0; i < 8; i++)
{
double ftn = evalsH(i);
if( fabs(ftn) == miniAbsValue )
{
i_minimum = i;
}
}
为什么不保留数组的绝对最小值,并仅在删除内容时重新计算它。添加内容时,可能需要对当前最小值进行简单比较和更新跟踪数组[0]的绝对值如果您只关心数据集中的最小/最大值,请考虑使用<代码>堆。它在<代码> O(1)<代码>中查找MI/MAX,插入<代码> O(Logn)并删除<代码> O(Logn)。
代码已经是最优的。正如其他人所指出的,如果你想提高性能,你需要一种不同的方法(例如更好的数据结构)。@NickZuber,我不需要最小值或最大值。相反,我需要具有最小绝对值的值。例如,在[-1,2,3,4]中,我将得到-1,而不是1。出于所有实际目的,std::set
不太可能更快,因为它在插入数字时必须遵循指针链,这只是在O(nlogn)操作上需要做的更多工作。这似乎给出了最小的绝对值。问题是找到具有最小ab的值
std::nth_element(v.begin(), v.begin(), v.end(), [](float& lhs, float& rhs){
return fabsf(lhs)<fabsf(rhs);
});
A = [5.1, -2.2, 8.2, -1, 4, 3, -5, 6]
double miniAbsValue = A.array().abs().minCoeff();
int i_minimum = 0; // to find the position of minimum absolute value
for(int i = 0; i < 8; i++)
{
double ftn = evalsH(i);
if( fabs(ftn) == miniAbsValue )
{
i_minimum = i;
}
}
A(i_minimum)