Если Вы хотите больше гибкости, чем 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")));
(Последний из комментария к исходному сообщению.)
Ваша задача - вычислить не факториал, а количество нулей. Хорошее решение использует формулу из 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. Это бозосорт. Такие решения требуют секунд времени для больших чисел.
Вам действительно нужно только знать, сколько двоек и пятерок в продукте. Если вы считаете конечные нули, то вы 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
Тип double имеет ограниченную точность, поэтому, если числа, с которыми вы работаете, становятся слишком большими, double будет только приближением. Чтобы обойти это, вы можете использовать что-то вроде BigInteger, чтобы заставить его работать с произвольно большими целыми числами.
Вы можете использовать DecimalFormat для форматирования больших чисел. Если вы отформатируете свое число таким образом, вы получите число в научной записи , тогда каждое число будет похоже на 1.4567E7, это значительно упростит вашу работу. Потому что число после E - количество знаков после. думаю, количество нулей в конце.
Я не знаю, нужен ли это точный образец. Вы можете увидеть, как формировать шаблоны здесь
DecimalFormat formater = new DecimalFormat("0.###E0");
Максимальное количество удвоений в Java составляет немного больше 9 * 10 ^ 18, где 25! равно 1,5 * 10 ^ 25. Если вы хотите иметь такие высокие факториалы, вы можете использовать BigInteger (аналогично BigDecimal, но не использует десятичные дроби).
Мои 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));
}
}
Я написал это очень быстро, я думаю, что это точно решит вашу проблему. Я использовал класс 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;
}
}