2的十万次幂怎么求?用Java做

这是一道作业。因为普通的求法内容会溢出,无法正常输出。所以回答前务必确定能正常输出。
提示可以用数组
大神求教一下,这是老师布置的作业,用Math.pow()或for循环10万遍,都不能输出,int,long存不了那么大的数。我是初学者,求教怎么算。

阅读 7.1k
8 个回答

高精度算法

原理简单来说就是用数组来存数字,然后手工模拟竖式运算。
网上资料很多的,随便搜搜就知道了。

因为对于Java不熟悉,且没有Java环境,我给你一个思路,定义一个长度为10000的数字,2作为初值传入数组的最后一位,然后两层循环,第一层循环为10000次,内部循环为数组存入字符的内容循环,对于存入内容的数组,每一位*2,如果大于10,就将进位存入前一位数组即可。结果集可以直接打印数组或者转成字符串输出。 我本想提供计算结果的,但是长度太长,超出评论范围了,我给你下计算结果的长度,让你用来做验证,计算结果的长度为30103位。

再一次修正了下代码,测试了下大于10的数字也可以正常执行了

public class PowerTest {

    public int[] power(int base, int index) {
        int[] end = new int[] { 1 };
        for (int i = 0; i < index; i++) {
            int carry = 0;
            for (int j = 0; j < end.length; j++) {
                if (j == end.length - 1) {
                    if ((end[j] * base + carry) / 10 > 0) {
                        int tmp1 = end[j];
                        end[j] = (end[j] * base + carry) % 10;
                        int[] expansion = new int[j + 2];
                        System.arraycopy(end, 0, expansion, 0, end.length);
                        expansion[j + 1] = (tmp1 * base + carry) / 10;
                        end = expansion;
                    } else {
                        end[j] = end[j] * base + carry;
                    }
                    break;
                }
                int tmp = end[j];
                end[j] = (end[j] * base + carry) % 10 >= 0 ? ((end[j] * base + carry) % 10) : (end[j] * base + carry);
                carry = (tmp * base + carry) / 10;
            }
        }
        return end;
    }

    @Test
    public void test() {
        int[] a = power(12, 10);
        System.out.println(a.length);
        StringBuffer sb = new StringBuffer(Arrays.toString(a));
        System.out.println(sb.reverse().substring(1, sb.length() - 1));
    }
}

应评论的要求补充一点内容
昨天夜里最原始的想法是利用2进制乘法移位的原理来完成楼主的这个需求,但是确实如评论所说会有精度上的问题
所以结合了@Carson的回复和自己的想法,写了一段代码(如下)。
代码的主要思路是,传入需要计算幂的数字,以及幂的次数(测试过程中只保证了10以内数字的n次幂,大于10的数字暂时还没测试)。计算的过程是模拟人类手工乘法计算的原理,讲乘数写入到数组中,然后逐位进行乘法,每一位大于10的时候产生进位,需要注意的是,在乘到最后一位时,如果发现要进位,那么需要做特殊处理,因为原有的数组长度不够了,因此引用了一个新数组,长度为原有的数组+1,这样可以解决最后一位进位的问题。
到这里主要的计算逻辑基本结束了,但是由于我写的算法是正向的,所以会导致最后的结果排列是倒序的,类似2^10次幂=1024,我的算法结果则会是4201,所以在测试类中做了一步字符串转换,并倒置了一下结果,以保证结果可以正常查看。


楼下的建议是正解,我昨天半夜里的想法确实不靠谱,晚点补个代码出来吧
代码补上。。。简单测了下,应该没问题

public class PowerTest {

    public int[] power(int base, int index) {
        int[] end = new int[] { 1 };
        for (int i = 0; i < index; i++) {
            int carry = 0;
            for (int j = 0; j < end.length; j++) {
                if (j == end.length - 1) {
                    if (end[j] * base + carry - 10 >= 0) {
                        end[j] = end[j] * base + carry - 10;
                        int[] expansion = new int[j + 2];
                        System.arraycopy(end, 0, expansion, 0, end.length);
                        expansion[j + 1] = 1;
                        end = expansion;
                    } else {
                        end[j] = end[j] * base + carry;
                    }
                    break;
                }
                int tmp = end[j];
                end[j] = end[j] * base + carry - 10 >= 0 ? (end[j] * base + carry - 10) : (end[j] * base + carry);
                carry = tmp * base + carry - 10 >= 0 ? 1 : 0;
            }
        }
        return end;
    }

    @Test
    public void test() {
        int[] a = power(2, 20);
        StringBuffer sb = new StringBuffer(Arrays.toString(a));
        System.out.println(sb.reverse().substring(1, sb.length() - 1));
    }
}

@Carson 的建议也许是你老师想考你的地方。如果目的不是测试的,一种更基本的办法是用BigIneteger。例如:

BigInteger.valueOf(2).pow(100_000);

实现了一个,但是效率不高:

import java.util.Arrays;

public class Application {

    public static void main(String[] args) {
        // 计算2的10万次方
        int[] num  = new int[]{1};
        for (int i = 0; i < 100000; i++) {
            //做10万次乘以2的计算
            num = timesTwo(num);
        }
        System.out.println("result= "+Arrays.toString(num)
                .replace(", ","")
                .replace("[","")
                .replace("]",""));
    }


    public static int[] timesTwo(int[] num) {
        //对最新一个结果,从最低位开始每一位都乘以2,并存储其值
        for (int i = num.length -1; i >= 0 ; i--) {
            num[i] *= 2;
        }
        //从最低位开始检查每一位是否溢出,并处理溢出
        for (int i = num.length -1; i >=0 ; i--) {//判断是否大于等于10
            //如果溢出
            if (num[i] >= 10) {
                //设置当前位的值
                num[i] -= 10;
                //如果当前位刚好是最高位
                if (i==0){
                    //扩大数组
                    int[] temp = new int[num.length+1];
                    //复制旧数组数据
                    System.arraycopy(num,0,temp,1,num.length);
                    //最高位为1
                    temp[0] = 1;
                    //引用新扩大后的数组
                    num = temp;
                }else{
                    //当前位的左边一位加1
                    num[i-1] += 1;
                }
            }
        }
        return num;
    }

}

用数组模拟一个二进制数字,幂次就往数组最后插0。

最后得出一个二进制的数组。然后二进制数组转十进制字符串。

初学者被布置这样的作业,老师的意思应该不是让你自己实现一个方法。
import java.io.File;
import java.io.PrintStream;
import java.math.BigInteger;

public class A {

public static void main(String[] args) {
    try {
        String s = new BigInteger("2").pow(100000).toString();
        //打印到d盘num.txt中,因为数字太长控制台打印不下
        System.setOut(new PrintStream(new File("d:\\num.txt")));
        System.out.print(s);
    }
    catch(Exception e){
        e.printStackTrace();
    }
}

}

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题