Подсчет конечных нулей чисел следовал из факториала

Если Вы хотите больше гибкости, чем BitConverter, но не хотите тех неуклюжий стиль 1990-х явные циклы, то можно сделать:

String.Join(String.Empty, Array.ConvertAll(bytes, x => x.ToString("X2")));

Или, если Вы используете.NET 4.0:

String.Concat(Array.ConvertAll(bytes, x => x.ToString("X2")));

(Последний из комментария к исходному сообщению.)

7
задан dfa 23 July 2009 в 23:44
поделиться

7 ответов

Ваша задача - вычислить не факториал, а количество нулей. Хорошее решение использует формулу из http://en.wikipedia.org/wiki/Trailing_zeros (которую вы можете попытаться доказать)

def zeroes(n):
    i = 1
    result = 0
    while n >= i:
        i *= 5
        result += n/i  # (taking floor, just like Python or Java does)
    return result

Надеюсь, вы сможете перевести ее на Java. Это просто вычисляет [n / 5] + [n / 25] + [n / 125] + [n / 625] + ... и останавливается, когда делитель становится больше, чем n.

НЕ используйте BigInteger. Это бозосорт. Такие решения требуют секунд времени для больших чисел.

17
ответ дан 6 December 2019 в 05:43
поделиться

Вам действительно нужно только знать, сколько двоек и пятерок в продукте. Если вы считаете конечные нули, то вы re на самом деле считает «Сколько раз десять делит это число?». если представляешь! как q * (2 ^ a) * (5 ^ b), где q не делится на 2 или 5. Тогда просто взяв минимум a и b во втором выражении, вы получите, сколько раз 10 делит число. На самом деле умножение - это излишне.

Изменить: подсчет двоек - тоже излишний, поэтому вам действительно нужны только пятерки.

И для некоторых питонов, я думаю, это должно сработать:

def countFives(n):
    fives = 0   
    m = 5
    while m <= n:
        fives = fives + (n/m)
        m = m*5
    return fives
14
ответ дан 6 December 2019 в 05:43
поделиться

Тип double имеет ограниченную точность, поэтому, если числа, с которыми вы работаете, становятся слишком большими, double будет только приближением. Чтобы обойти это, вы можете использовать что-то вроде BigInteger, чтобы заставить его работать с произвольно большими целыми числами.

3
ответ дан 6 December 2019 в 05:43
поделиться

Вы можете использовать DecimalFormat для форматирования больших чисел. Если вы отформатируете свое число таким образом, вы получите число в научной записи , тогда каждое число будет похоже на 1.4567E7, это значительно упростит вашу работу. Потому что число после E - количество знаков после. думаю, количество нулей в конце.

Я не знаю, нужен ли это точный образец. Вы можете увидеть, как формировать шаблоны здесь

DecimalFormat formater = new DecimalFormat("0.###E0");
1
ответ дан 6 December 2019 в 05:43
поделиться

Максимальное количество удвоений в Java составляет немного больше 9 * 10 ^ 18, где 25! равно 1,5 * 10 ^ 25. Если вы хотите иметь такие высокие факториалы, вы можете использовать BigInteger (аналогично BigDecimal, но не использует десятичные дроби).

-1
ответ дан 6 December 2019 в 05:43
поделиться

Мои 2 цента: избегайте работы с двойными, поскольку они подвержены ошибкам. Лучшим типом данных в этом случае является 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));
    }
}
0
ответ дан 6 December 2019 в 05:43
поделиться

Я написал это очень быстро, я думаю, что это точно решит вашу проблему. Я использовал класс BigInteger, чтобы избежать преобразования двойного в целое число, которое могло вызывать у вас проблемы. Я протестировал его на нескольких больших числах, превышающих 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;
    }
}
-1
ответ дан 6 December 2019 в 05:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: