大哥 教教小弟我吧 1+2+3+4......+n<8888求N用JAVA来编.我真整不会了.
解决方案 »
- 关于日期与星期的问题
- java中API有点不明白的地方
- JGraph求救!
- 求助:关于SNMP trap的消息中含有中文字符问题
- 本人用swing和数据库连接做了一个小程序,代码如下!!!
- 如何对Windows桌面进行控制?比如锁定“开始”,“桌面图标”等?
- 如何实现3层依次Overlay的JPanel(大小相同),而且每层JPanel均为可见,即上2层的JPanel为“透明”
- 请教在jbuild中如何画曲线,回答清楚给分
- 我是新手,请问Jbuilder中的控件怎样调整大小和位置,请大虾多多指点
- 有没有好的适合新手看的代码实际案例比较多的书籍,面向对象学的不好
- 电子词典的hash算法
- Java网络问题
public static void main(String[] args) {
int i = 0;
for (; i < 8888; i++) {
if ((i^2+i) >= 8888 * 2)
break;
}
System.out.println("你要的n:=" + (i-1));
}
}简单实现
public static void main(String[] args) {
int i = 0;
while((i^2+i) < 8888 * 2){
i++;
}
System.out.println("你要的n:=" + (i-1));
}
} 简单实现
public static void main(String args[]){
int a1=1,d=1,an=0,Sn=0,n=0;
for(n=1;;n++){
an=a1+n*d;
Sn=Sn+an;
if(Sn>8888)
break;
}
System.out.println("n="+(n-1));
}
}
public static void main(String args[]){
int a1=1,d=1,an=0,Sn=0,n=0;
for(n=1;;n++){
an=a1+(n-1)*d;
Sn=Sn+an;
System.out.println(n+":"+Sn);
if(Sn>8888)
break;
}
System.out.println("n="+(n-1));
}
}
加法的效率比乘法和平方高多了~
干嘛放着简单的高效方法不用呢~int sum = 0;
int n = 1;
while(true){
sum += n;
if (sum >= 8888){
break;
}
n ++;
}
System.out.println("N = " + n);
return Math.floor((Math.floor(Math.sqrt(1 + 8 * 8888)) - 1) / 2);^表示乘方是VB的语法吧?Java中用Math.pow()。
00101010 42
^00001111 15
-----------
00100101 37
你可以看看操作系统和计算机原理,了解一下什么样的运算才是高效的~计算机的高效算法就是加减法(+-)和移位(<<、>>、>>>)是效率最高的~
for循环也是高效的,因为计算机的简单计数是硬件(计数器)直接实现的~
public static void main(String args[]){
int sum=0;
int n=1;
do{
n++;
//sum=(n+1)*n/2; //这个也能用,2个选1
sum=(int)(Math.pow(n,2)+n)/2;//这个是用平方的
}while(sum<8888);
System.out.println("n="+(n-1));
}
}
Math.sqrt()是一个本地方法,相信效率不会低到哪里去,开方运算如果用牛顿迭代法,效率至少要高于O(n)。我分别用循环和开平方算法测试了楼主的问题,在我的电脑上,当S=8888时看不出差别,但是,当我用S=Long.MaxValue分别测试,循环方法将近30秒才给出结果,而我的算法时间依然不到半秒。可知Math.sqrt()的效率不低。
还有用pow(n, 2)的兄弟, 你直接用n * n不就得了 这个问题显然用 牛顿迭代法更快,要相信数学的力量。PS:
GBBasic,QB,VB中 ^表示乘方,Basic语系基本都是这样的。
很多语言用 **来表示乘方,比如Ruby。
^在Pascal中是 指针指示。在C类语法(includeing C/C++/Java/C#)中表示位运算。
给你完整的测试代码和测试结果,不知道你用什么电脑跑的测试,竟然用30秒~~~~
你从结果也可以看到哪种算法好坏来了~那个用floor等一系列函数的我没用最大值,没看出来为什么用8~~~
public static void main(String[] args) {
int max = Integer.MAX_VALUE-1000;
long t1 = System.currentTimeMillis();
int sum = 0,i = 1;
for (i = 1; ; i ++){
sum += i;
if (sum >= max){
break;
}
}
System.out.println("N = " + i);
long t2 = System.currentTimeMillis();
System.out.println("第一次使用时间 t1 = " + (t2-t1) + "毫秒");
long t3 = System.currentTimeMillis();
sum = 0;
i = 1;
while(true){
sum += i;
if (sum >= max){
break;
}
i ++;
}
System.out.println("N = " + i);
long t4 = System.currentTimeMillis();
System.out.println("第二次使用时间 t2 = " + (t4-t3) + "毫秒");
}
第1次测试结果:
N = 5004393
第一次使用时间 t1 = 15毫秒
N = 5004393
第二次使用时间 t2 = 0毫秒
第2次测试结果:
N = 5004393
第一次使用时间 t1 = 16毫秒
N = 5004393
第二次使用时间 t2 = 0毫秒
第3次测试结果:
N = 5004393
第一次使用时间 t1 = 15毫秒
N = 5004393
第二次使用时间 t2 = 0毫秒
第4次测试结果:
N = 5004393
第一次使用时间 t1 = 16毫秒
N = 5004393
第二次使用时间 t2 = 0毫秒
第5次测试结果:
N = 5004393
第一次使用时间 t1 = 16毫秒
N = 5004393
第二次使用时间 t2 = 0毫秒哪一次测试时间也没超过20毫秒,我不知道你的30秒是用什么电脑测出来的~
对于return Math.floor((Math.floor(Math.sqrt(1 + 8 * max)) - 1) / 2);
我不知道你怎么额出来的结果:
当max接近Integer.MAX_VALUE,很明显8 * max已经溢出了,已经严重出错了,那你还怎么测呢~~
多多考虑些因素,不是脑袋一热就能想完美的~
for (int n = 0; n < 5; n ++){
System.out.println("第" + (n+1) + "次测试结果:");
long t1 = System.currentTimeMillis();
int sum = 0,i = 1;
for (i = 1; ; i ++){
sum += i;
if (sum >= max || Integer.MAX_VALUE-sum < i){
break;
}
}
System.out.println("N = " + i);
long t2 = System.currentTimeMillis();
System.out.println("第一次使用时间 t1 = " + (t2-t1) + "毫秒");
long t3 = System.currentTimeMillis();
sum = 0;
i = 1;
while(true){
sum += i;
if (sum >= max || Integer.MAX_VALUE-sum < i){
break;
}
i ++;
}
System.out.println("N = " + i);
long t4 = System.currentTimeMillis();
System.out.println("第二次使用时间 t2 = " + (t4-t3) + "毫秒");
}
}
测试结果:
第1次测试结果:
N = 65535
第一次使用时间 t1 = 0毫秒
N = 65535
第二次使用时间 t2 = 0毫秒第2次测试结果:
N = 65535
第一次使用时间 t1 = 0毫秒
N = 65535
第二次使用时间 t2 = 0毫秒第3次测试结果:
N = 65535
第一次使用时间 t1 = 0毫秒
N = 65535
第二次使用时间 t2 = 0毫秒第4次测试结果:
N = 65535
第一次使用时间 t1 = 0毫秒
N = 65535
第二次使用时间 t2 = 0毫秒第5次测试结果:
N = 65535
第一次使用时间 t1 = 0毫秒
N = 65535
第二次使用时间 t2 = 0毫秒第6次测试结果:
N = 65535
第一次使用时间 t1 = 0毫秒
N = 65535
第二次使用时间 t2 = 0毫秒第7次测试结果:
N = 65535
第一次使用时间 t1 = 0毫秒
N = 65535
第二次使用时间 t2 = 0毫秒第8次测试结果:
N = 65535
第一次使用时间 t1 = 0毫秒
N = 65535
第二次使用时间 t2 = 0毫秒第9次测试结果:
N = 65535
第一次使用时间 t1 = 0毫秒
N = 65535
第二次使用时间 t2 = 0毫秒第10次测试结果:
N = 65535
第一次使用时间 t1 = 0毫秒
N = 65535
第二次使用时间 t2 = 0毫秒
public static void main(String[] args) {
double timeStart, timeEnd; /* 使用循环 */
timeStart = System.currentTimeMillis();
System.out.println(maxLoop(Long.MAX_VALUE));
timeEnd = System.currentTimeMillis();
System.out.println("使用循环耗时:" + (timeEnd - timeStart) + " ms"); /* 使用Math.sqrt()方法 */
timeStart = System.currentTimeMillis();
System.out.println(maxSQRT(Long.MAX_VALUE));
timeEnd = System.currentTimeMillis();
System.out.println("使用Math.sqrt()耗时:" + (timeEnd - timeStart) + " ms"); } static double maxLoop(double s) {
double i = 0;
for (; i < s; i++)
if ((i * i + i) >= s * 2)
break;
return i-1;
} static double maxSQRT(double s) {
return Math.floor((Math.floor(Math.sqrt(1 + 8 * s)) - 1) / 2);
}
}测试结果:
4.294967295E9
使用循环耗时:27922.0 ms
4.294967295E9
使用Math.sqrt()耗时:0.0 ms
对于return Math.floor((Math.floor(Math.sqrt(1 + 8 * max)) - 1) / 2);
我不知道你怎么额出来的结果:
当max接近Integer.MAX_VALUE,很明显8 * max已经溢出了,已经严重出错了,那你还怎么测呢~~
多多考虑些因素,不是脑袋一热就能想完美的~
----------------------------拜托老兄你有空看看api,Math.sqrt()的参数类型是double,1+8*max的值会自动提升为double,无论如何也不存在所谓的溢出问题。还有奉劝一定要相信api,api可以说是精英智慧的结晶,难不成你求平方根也要去用循环穷举?再奉劝凡事不要过于自信,学了几天原理没什么值得摆谱的,谁都知道计算机做加减、移位效率最高,学点算法基础再来摆谱吧(不过相信到时你会摆得更厉害了,哈哈)。不好意思,我心情激动,言辞过激,抱歉。
你给出的代码在后,人家评论在前,怎么就说人家说错了呢,只在没了解你怎么用的Long.MAX_VALUE/Integer.MAX_VALUE罢了
1+8 * Long.MAX_VALUE确实是溢出的啊
它不同于:
1+8*changeType(Long.MAX_VALUE)。我并不是说那样会很快,但你这个方法是用人脑做了部分工作得来的。
就好像你问一个小学生从1加到100结果是多少,他老老实实的一个一个加出来得5050;
而一个中学生就会(1+100)*100/2也得到5050。
很明显中学生效率高,但却需要一定的数学知识才可理解。小学生高明不高明也不是一棒子打死的,至少他最接近本来的需求,易懂,而且在规模比较小的时候会快些
另外,你在循环的方法中每次都乘一下来代替原来的方法,自然要更慢............
既然ls提出来了,我想有必要说一点,本来是不打算说的,没必要计较~从static double maxSQRT(double s) {
return Math.floor((Math.floor(Math.sqrt(1 + 8 * s)) - 1) / 2);
}
到System.out.println(maxSQRT(Long.MAX_VALUE));根本就是不等价转化,
从人脑的考虑没错,但从计算机角度考虑就存在问题~都知道
maxLong = 9223372036854775807
maxDouble = 1.7976931348623157E308
也就是,
Long.MAX_VALUE=9223372036854775807,19位长度;
Double.MAX_VALUE=1.7976931348623157E308是18位小数,
看起来没什么问题~其实不然:
maxLong2Double=9.223372036854776E18
浮点数的小数点部分真正精确位其实只有15位,
也就是Long.MAX_VALUE转化为double时根本就不等价~所以虽然结果是正确的,但是方法根本就不对~
有时间还是多看看计算机基础的书吧,充充电~
软件的基础还是计算机,不要忘本~