我有一系列整数,我想计算有多少not 1
个数字:
int* t = new int[50];
int counter = 1;
for(int i = 0; i < 50; i++){
t[i] = i % 10;
if((memcmp((void*)t[i], (void*)1, 4) != 0)){
counter++;
}
}
但我得adress violation
。如何使它工作......快速工作。你知道更快的解决方案,而不是标准解决方案请不要t[i]==1
。
编辑:
因为我在程序中使用了大小为362856427
的数组,所以我希望简化它。
答案 0 :(得分:5)
为什么不这样做:
int* t = new int[50];
int counter = 0; // <-- Shouldn't it be "0" at the beginning?
for(int i = 0; i < 50; i++){
if(t[i] != 1){
counter++;
}
}
答案 1 :(得分:2)
您在地址上进行了类型转换。这意味着您要在地址1处进行比较,而不是1对比。您的解决方案是创建int one = 1;
,然后将&one
替换为(void*)1
。
答案 2 :(得分:1)
TL; DR :以明显的方式执行,并确保您的编译器对其进行优化。
如果没有完整,可重复的程序示例,很难对性能进行推理。因此,让我们从简单的实施开始:
#include <array>
#include <algorithm>
std::array<int, 362856427> a = {};
int main()
{
a[500] = 1;
a[5000] = 1;
a[50000] = 1;
a[500000] = 1;
auto counter = 0u;
for (auto i = 0u; i < a.size(); ++i) {
if (a[i] != 1)
++counter;
}
return counter != 362856423;
}
为此,我获得了1.79秒的用户时间。然后我意识到我的错误,并将-O3
添加到我的编译命令中。那更好:
g++ -std=c++17 -g -Wall -Wextra -O3 16385733.cpp -o 16385733
time ./16385733
0.07user 0.08system 0:00.16elapsed 98%CPU (0avgtext+0avgdata 2212maxresident)k
我们可以尝试简化循环,但这没有任何可衡量的差异(优化器已经击败了我们这个):
for (auto i = 0u; i < a.size(); ++i)
counter += a[i] != 1;
另一种选择是通过使用标准算法使代码更清晰:
auto counter = a.size() - std::count(a.begin(), a.end(), 1);
这比明显的循环持续时间长50%。
如果你的输入数组要大得多,你可以通过并行化计算来获得:
auto counter = 0ul;
#pragma omp parallel for reduction(+:counter)
for (auto i = 0ul; i < a.size(); ++i)
counter += a[i] != 1;
我的基准测试显示,当数组大小为362856427时,它与标准算法一样慢,当它增加到3628564270时没有更快。
有几种方法可以用同等形式重写:
for (auto i: a)
counter += i != 1;
for (auto p = a.data(); p < end; ++p)
counter += *p != 1;
所有这些都表现出类似的性能,并且OpenMP没有得到改善。
所以简短的回答是
答案 3 :(得分:0)
在C ++ 1x中,您可以使用std::count
:
const int N = 50;
int* t = new int[N];
int counter = N - std::count(t, t+N, 1);