/// <summary> /// 计算min 到max 能被x或y整除的数的和 /// </summary> /// <param name="min"></param> /// <param name="max"></param> /// <param name="x"></param> /// <param name="y"></param> /// <returns></returns> public static int GetValue(int min, int max, int x, int y) { var result = 0; for (var i = min / x; i <= max / x; i++) { var temp = i * x; if (temp >= min && temp <= max) { result += temp; } } for (var i = min / y; i <= max / y; i++) { var temp = i * y; if (temp >= min && temp <= max && temp % x != 0) { result += temp; } } return result; }
刚作了个测试,结果比较有趣,Linq远远落后,得到最后一名,可能Enumerator的开销比较高:min = 10, max = 10000, x = 3, y = 5; 循环100000次)1、sum steps: 12毫秒 (代码见25楼) 2、sum linq: 20秒 3、sum getvalue: 4秒 (代码见31楼) 4、sum getvalueEx: 2秒 (代码随后发上) 5、sum loop: 7秒 (代码见37楼)min = 10, max = 100, x = 3, y = 5; 循环100000次) 1、sum steps: 12ms 2、sum linq: 205ms 3、sum getvalue: 43ms 4、sum getvalueEx: 24ms 5、sum loop: 72ms测试代码如下:private static void Main() { int loop = 100000; int min = 10, max = 10000, x = 3, y = 5, sum = 0; Stopwatch watch = new Stopwatch(); watch.Restart(); for (int i = 0; i < loop; i++) { sum = SumSteps(min, max, x, y); } Console.WriteLine("sum step: {0} in {1} ms", sum, watch.ElapsedMilliseconds); watch.Restart(); for (int i = 0; i < loop; i++) { sum = Enumerable.Range(min, max - min + 1).Where(n => n % x == 0 || n % y == 0).Sum(); } Console.WriteLine("sum linq: {0} in {1} ms", sum, watch.ElapsedMilliseconds); watch.Restart(); for(int i=0; i<loop; i++) { sum = GetValue(min, max, x, y); } Console.WriteLine("sum getvalue: {0} in {1} ms", sum, watch.ElapsedMilliseconds); watch.Restart(); for (int i = 0; i < loop; i++) { sum = GetValueEx(min, max, x, y); } Console.WriteLine("sum getvalueex: {0} in {1} ms", sum, watch.ElapsedMilliseconds); watch.Restart(); for (int i = 0; i < loop; i++) { int sum4 = SumLoop(min, max, x, y); } Console.WriteLine("sum loop: {0} in {1} ms", 0, watch.ElapsedMilliseconds); }
如下是对31楼代码进行一定优化。public static int GetValueEx(int min, int max, int x, int y) { var result = 0; for (var i = min + (x - min % x) % x; i <= max; i += x) { result += i; } for (var i = min + (y - min % y) % y; i <= max; i += y) { if (i % x != 0) result += i; } return result; }1、乘/除/模运算比加减慢,减少乘除操作; 2、条件语句比较慢(不利于CPU的指令预测),第一个循环体中去掉条件判断。 3、减少指令注:初学者完全无须害怕条件语句和乘除运算。这种优化属于局部优化,它的影响相较于‘算法优化’可能是九牛一毛。
eg当i=3跟i=5的时候,同时算了15这个数所以还是循环直接,不用再去考虑重复
你这样写还得多判断一些条件
var result= lstInt.Where(p=>p%5==0 && p%3==0).Sum();
项数:(199-101)/2+1=50
和为:(199+101)*50/2=7500
当有公式就按公式去设计,否则,难免使用最原始的循环设计简洁明了不易发生错误。
int 起数(100), 止数(200), 奇数和 = ((止数 - 1) + (起数 + 1)) * (((止数 - 1) - (起数 + 1)) / 2 + 1) / 2;
公式直接计算不需要循环。
80000当更改参数时算式程序不需要变动都适用。
况且数百范围内对现在计算机来说如白驹过隙,弹指一挥间,根本算不得什么事,循环影响可以不计。
1). 2 * 5 = 10 , 10 应该是符合条件的值,
2). 当某个数 能同时被 3 和 5 整除 时 重复加入 result, 如 i = 3 时 , result += i * 5 , i = 5 时 , result += i * 3另外, Linq 应该也是做了 10 - 100 的循环?
{
private static void Main()
{
List<int[]> dataList = new List<int[]>()
{
new int[]{10, 100, 3, 5}, // 2395
new int[]{12, 100000, 102, 99}, // 111115
new int[]{7, 49, 7, 49}, // 196
}; foreach (var d in dataList)
{
int sumStep = SumSteps(d[0], d[1], d[2], d[3]);
int sumLinq = Enumerable.Range(d[0], d[1] - d[0] + 1).Where(i => i % d[2] == 0 || i % d[3] == 0).Sum();
System.Diagnostics.Trace.Assert(sumStep == sumLinq);
}
} public static int SumSteps(int start, int end, int pace1, int pace2)
{
int lcm = LeastCommonMultiple(pace1, pace2);
int sumToEnd = SumSteps(end + 1, pace1) + SumSteps(end + 1, pace2) - SumSteps(end + 1, lcm);
int sumToStart = SumSteps(start, pace1) + SumSteps(start, pace2) - SumSteps(start, lcm);
return sumToEnd - sumToStart;
} static int SumSteps(int cellingExclusive, int pace)
{
int count = (cellingExclusive - 1) / pace;
return count * (count + 1) / 2 * pace;
} static int LeastCommonMultiple(int a, int b)
{
return a / GreatestCommonDivisor(a, b) * b;
} static int GreatestCommonDivisor(int a, int b)
{
return b == 0 ? a : GreatestCommonDivisor(b, a % b);
}
}
4种循环,for,while,foreach,while...do
或者写成递归,其实还是循环
int result=0;
for(int i=2,i<34,i++)
{
if(i*3>=10&&i*3<=100)
{
result+=i*3;
}
}
for(int i=2,i<=20,i++)
{
if(i*5>=10&&i*5<=100)
{
result+=i*5;
}
}
for(int i=3,i<34,i++)
{
if(i*3>=10&&i*3<=100)
{
result+=i*3;
}
}
for(int i=2,i<=20,i++)
{
if(i*5>=10&&i*5<=100)
{
result+=i*5;
}
}
与
直接for循环一遍
哪个比较快一点。如果 这么写,通用性 太弱。
/// <summary>
/// 计算min 到max 能被x或y整除的数的和
/// </summary>
/// <param name="min"></param>
/// <param name="max"></param>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns></returns>
public static int GetValue(int min, int max, int x, int y)
{
var result = 0;
for (var i = min / x; i <= max / x; i++)
{
var temp = i * x;
if (temp >= min && temp <= max)
{
result += temp;
}
}
for (var i = min / y; i <= max / y; i++)
{
var temp = i * y;
if (temp >= min && temp <= max && temp % x != 0)
{
result += temp;
}
}
return result; }
如果i1 * x=i2 * y,则重复计算了.
想去掉重复,你要花费更多的运算,最终可能一点不比遍历的运算量小.
for (int i = 10;i<=100;i++)
{
if( i%3==0 || i%5==0)
{
sum+=i;
}
}这样的代码,不是一眼明了么。
就算改需求了,变成10到1000了,也就是多加一个0而已。
虽然效率是不够。
//可以用这个公式来算
//Min =下限 ,题目里是10
//Max = 上限,题目里是100
//Sum(n) 函数 求 1~n的和
Min + 3 * (Sum(Max / 3) - Sum(Min / 3)) + 5 * (Sum(Max / 5) - Sum(Min / 5)) - 15 * (Sum(Max / 15) - Sum(Min / 15))
2、sum linq: 20秒
3、sum getvalue: 4秒 (代码见31楼)
4、sum getvalueEx: 2秒 (代码随后发上)
5、sum loop: 7秒 (代码见37楼)min = 10, max = 100, x = 3, y = 5; 循环100000次)
1、sum steps: 12ms
2、sum linq: 205ms
3、sum getvalue: 43ms
4、sum getvalueEx: 24ms
5、sum loop: 72ms测试代码如下:private static void Main()
{
int loop = 100000;
int min = 10, max = 10000, x = 3, y = 5, sum = 0;
Stopwatch watch = new Stopwatch(); watch.Restart();
for (int i = 0; i < loop; i++)
{
sum = SumSteps(min, max, x, y);
}
Console.WriteLine("sum step: {0} in {1} ms", sum, watch.ElapsedMilliseconds); watch.Restart();
for (int i = 0; i < loop; i++)
{
sum = Enumerable.Range(min, max - min + 1).Where(n => n % x == 0 || n % y == 0).Sum();
}
Console.WriteLine("sum linq: {0} in {1} ms", sum, watch.ElapsedMilliseconds); watch.Restart();
for(int i=0; i<loop; i++)
{
sum = GetValue(min, max, x, y);
}
Console.WriteLine("sum getvalue: {0} in {1} ms", sum, watch.ElapsedMilliseconds); watch.Restart();
for (int i = 0; i < loop; i++)
{
sum = GetValueEx(min, max, x, y);
}
Console.WriteLine("sum getvalueex: {0} in {1} ms", sum, watch.ElapsedMilliseconds); watch.Restart();
for (int i = 0; i < loop; i++)
{
int sum4 = SumLoop(min, max, x, y);
}
Console.WriteLine("sum loop: {0} in {1} ms", 0, watch.ElapsedMilliseconds);
}
{
var result = 0;
for (var i = min + (x - min % x) % x; i <= max; i += x)
{
result += i;
}
for (var i = min + (y - min % y) % y; i <= max; i += y)
{
if (i % x != 0) result += i;
}
return result;
}1、乘/除/模运算比加减慢,减少乘除操作;
2、条件语句比较慢(不利于CPU的指令预测),第一个循环体中去掉条件判断。
3、减少指令注:初学者完全无须害怕条件语句和乘除运算。这种优化属于局部优化,它的影响相较于‘算法优化’可能是九牛一毛。
return v*(v+1)/2;
}
long getsum(long min,long max){
return min + 3 * (sum(max / 3) - sum(min / 3)) + 5 * (sum(max / 5) - sum(min / 5)) - 15 * (sum(max / 15) - sum(min / 15));
}