Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 计算由阶乘产生的数字的尾随零_Java_Correctness - Fatal编程技术网

Java 计算由阶乘产生的数字的尾随零

Java 计算由阶乘产生的数字的尾随零,java,correctness,Java,Correctness,我试图计算由阶乘产生的数字的尾随零(这意味着数字变得相当大)。下面的代码获取一个数字,计算该数字的阶乘,并计算尾随的零。然而,当这个数字大约等于25,numzero不起作用 public static void main(String[] args) { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); double fact; int answer;

我试图计算由阶乘产生的数字的尾随零(这意味着数字变得相当大)。下面的代码获取一个数字,计算该数字的阶乘,并计算尾随的零。然而,当这个数字大约等于
25,numzero不起作用

public static void main(String[] args) {
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    double fact;
    int answer;
        
    try {
        int number = Integer.parseInt(br.readLine());
        fact = factorial(number);
        answer = numZeros(fact);
    }
    catch (NumberFormatException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

public static double factorial (int num) {
    double total = 1;
    for (int i = 1; i <= num; i++) {
        total *= i;
    }
    return total;
}   

public static int numZeros (double num) {
    int count = 0;
    int last = 0;   

    while (last == 0) {
        last = (int) (num % 10);
        num = num / 10;
        count++;
    }
    
    return count-1;
}
publicstaticvoidmain(字符串[]args){
BufferedReader br=新的BufferedReader(新的InputStreamReader(System.in));
双重事实;
int答案;
试一试{
int number=Integer.parseInt(br.readLine());
事实=阶乘(数字);
答案=num0(事实);
}
捕获(数字格式){
e、 printStackTrace();
}捕获(IOE异常){
e、 printStackTrace();
}
}
公共静态双阶乘(int-num){
双倍合计=1;

对于(int i=1;i你只需要知道乘积中有多少个2和5。如果你在计算尾随的零,那么你实际上在计算“10除以这个数字多少次?”。如果你把n!表示为q*(2^a)*(5^b)其中q不能被2或5整除。那么只需取第二个表达式中a和b的最小值,就可以得到10除以该数字的次数。实际上,进行乘法是多余的

编辑:数到二也太过分了,所以你真的只需要五

对于一些python,我认为这应该是可行的:

def countFives(n):
    fives = 0   
    m = 5
    while m <= n:
        fives = fives + (n/m)
        m = m*5
    return fives
def countFives(n):
五=0
m=5

而m你可以使用十进制格式来格式化大数字。如果你用这种格式来格式化你的数字,那么每个数字都会像1.4567E7,这将使你的工作更容易。因为E后面的数字-后面的字符数。我认为是尾随零的数量

我不知道这是否是所需的确切图案。你可以看看如何形成图案


double类型的精度有限,因此,如果您使用的数字太大,double将只是一个近似值。要解决这个问题,您可以使用类似BigInteger的东西使其适用于任意大的整数。

Java的double max out在9*10^18上一点,其中as 25!是1.5*10^25。如果您愿意能够有高阶乘,您可能希望使用BigInteger(类似于BigDecimal,但不使用小数).

我写得很快,我认为它准确地解决了您的问题。我使用BigInteger类来避免从double到integer的转换,这可能会给您带来问题。我在25以上的几个大数字上测试了它,例如101,它准确地返回了24个零

这个方法背后的思想是,如果你取25!那么第一次计算是25*24=600,所以你可以立即去掉两个零,然后再做6*23=138。所以它会计算阶乘消零

public static int count(int number) {
    final BigInteger zero = new BigInteger("0");
    final BigInteger ten = new BigInteger("10");
    int zeroCount = 0;
    BigInteger mult = new BigInteger("1");
    while (number > 0) {
        mult = mult.multiply(new BigInteger(Integer.toString(number)));
        while (mult.mod(ten).compareTo(zero) == 0){
            mult = mult.divide(ten);
            zeroCount += 1;
        }
        number -= 1;
    }
    return zeroCount;
}
因为你说你根本不关心运行时间(不是说我的第一个运行时间特别有效,只是稍微有效一点),所以这一个只做阶乘,然后计算零,所以实际上更简单:

public static BigInteger factorial(int number) {
    BigInteger ans = new BigInteger("1");
    while (number > 0) {
        ans = ans.multiply(new BigInteger(Integer.toString(number)));
        number -= 1;
    }
    return ans;
}

public static int countZeros(int number) {
    final BigInteger zero = new BigInteger("0");
    final BigInteger ten = new BigInteger("10");
    BigInteger fact = factorial(number);
    int zeroCount = 0;
    while (fact.mod(ten).compareTo(zero) == 0){
        fact = fact.divide(ten);
        zeroCount += 1;
    }
}

我的2美分:避免使用double,因为它们容易出错。在这种情况下,更好的数据类型是BigInteger,这里有一个小方法可以帮助您:

public class CountTrailingZeroes {

    public int countTrailingZeroes(double number) {
        return countTrailingZeroes(String.format("%.0f", number));
    }

    public int countTrailingZeroes(String number) {
        int c = 0;
        int i = number.length() - 1;

        while (number.charAt(i) == '0') {
            i--;
            c++;
        }

        return c;

    }

    @Test
    public void $128() {
        assertEquals(0, countTrailingZeroes("128"));
    }

    @Test
    public void $120() {
        assertEquals(1, countTrailingZeroes("120"));
    }

    @Test
    public void $1200() {
        assertEquals(2, countTrailingZeroes("1200"));
    }

    @Test
    public void $12000() {
        assertEquals(3, countTrailingZeroes("12000"));
    }

    @Test
    public void $120000() {
        assertEquals(4, countTrailingZeroes("120000"));
    }

    @Test
    public void $102350000() {
        assertEquals(4, countTrailingZeroes("102350000"));
    }

    @Test
    public void $1023500000() {
        assertEquals(5, countTrailingZeroes(1023500000.0));
    }
}

你的任务不是计算阶乘,而是计算零的数量。一个好的解决方案是使用公式(你可以试着证明)

希望您能将其转换为Java。这只需计算[n/5]+[n/25]+[n/125]+[n/625]+…并在除数大于n时停止


不要使用Biginteger。这是一个bozosort。这样的解决方案需要几秒钟的时间来处理大数。

我就是这样做的,但是对于大于25的阶乘,长容量是不够的,应该使用Biginteger类,我还不熟悉:)

publicstaticvoidmain(字符串[]args){
//TODO自动生成的方法存根
扫描仪输入=新扫描仪(系统输入);
System.out.print(“请输入一个数字:”);
long number=in.nextLong();
长numFactorial=1;

对于(长i=1;i对数时间复杂度的最佳值如下:

public int trailingZeroes(int n) {
    if (n < 0)
        return -1;

    int count = 0;
    for (long i = 5; n / i >= 1; i *= 5) {
        count += n / i;
    }

    return count;
}
public int trailingzero(int n){
if(n<0)
返回-1;
整数计数=0;
对于(长i=5;n/i>=1;i*=5){
计数+=n/i;
}
返回计数;
}

不知羞耻地抄袭了

我也有同样的问题要用Javascript解决,我像这样解决了:

var number = 1000010000;
var str = (number + '').split(''); //convert to string
var i = str.length - 1; // start from the right side of the array
var count = 0; //var where to leave result
for (;i>0 && str[i] === '0';i--){
    count++;
}
console.log(count) // console shows 4
此解决方案提供了尾随零的数量

var编号=1000010000;
var str=(数字+“”).split(“”);//转换为字符串
var i=str.length-1;//从数组的右侧开始
var count=0;//将结果留在何处的var
对于(;i>0&&str[i]=“0”;i--){
计数++;
}

console.log(计数)
我的猜测是因为您超过了双精度的大小。@jjnguy:是的,这是我的第一个猜测,但是25!小于Java的最大双精度。顺便说一句,numzero将返回-1表示1!、2!、3!、4!。我的猜测是,由于浮点错误,当您预期10时,您将得到9.99999999。我只是惊讶于它适用于s哦,朗。承认吧,你想解决这个问题:。>:我不明白你所说的数数乘积中有多少个2和5是什么意思。@bLee:得到尾随0的唯一方法是将一个可被2整除的数字乘以一个可被5整除的数字。2和5的每一对都会给你另一个尾随0。2和5是10的唯一两个素数。因为你想知道零的数目,你关心的是你的数字是否可以被10整除。如果你知道最后一个数字中有多少个2和5,你就知道它可以被10整除多少次。你为什么要计算2?你知道限制因素是5s@dfa不,你可以预测零的数量。只要数一数数字因子5在n以下的数字中出现的次数,以获得尾随零的数量
public static void main(String[] args) {
    // TODO Auto-generated method stub
    Scanner in = new Scanner(System.in);
    System.out.print("Please enter a number : ");
    long number = in.nextLong();
    long numFactorial = 1;

    for(long i = 1; i <= number; i++) {
        numFactorial *= i;
    }
    long result = 0;
    int divider = 5;
    for( divider =5; (numFactorial % divider) == 0; divider*=5) {
         result += 1;
    }

    System.out.println("Factorial of n is: " + numFactorial);
    System.out.println("The number contains " + result + " zeroes at its end.");

    in.close();

 }

}
public int trailingZeroes(int n) {
    if (n < 0)
        return -1;

    int count = 0;
    for (long i = 5; n / i >= 1; i *= 5) {
        count += n / i;
    }

    return count;
}
var number = 1000010000;
var str = (number + '').split(''); //convert to string
var i = str.length - 1; // start from the right side of the array
var count = 0; //var where to leave result
for (;i>0 && str[i] === '0';i--){
    count++;
}
console.log(count) // console shows 4