Какова сумма цифр числа 2 ^ 1000?
Это problem из Project Euler, и этот вопрос включает в себя некоторый исходный код, поэтому рассмотрите это предупреждение вашего спойлера, если вы заинтересованы в его решении самостоятельно. Не рекомендуется распространять решения проблем, и это не то, что я хочу. Я просто нуждаюсь в небольшом подтасовке и руководстве в правильном направлении, добросовестно.
Проблема гласит:
2 ^ 15 = 32768, а сумма его цифр равна 3 + 2 + 7 + 6 + 8 = 26.
Какова сумма цифр числа 2 ^ 1000?
Я понимаю предпосылку и математику проблемы, но я только начал практиковать С# неделю назад, поэтому мое программирование в лучшем случае шатко.
Я знаю, что int, long и double безнадежно неадекватны для того, чтобы точно удерживать 300 + (базовые 10) цифры 2 ^ 1000, поэтому необходима какая-то стратегия. Моя стратегия заключалась в том, чтобы установить вычисление, которое получает цифры один за другим, и надеемся, что компилятор сможет выяснить, как вычислить каждую цифру без некоторой ошибки, например, переполнения:
using System;
using System.IO;
using System.Windows.Forms;
namespace euler016
{
class DigitSum
{
// sum all the (base 10) digits of 2^powerOfTwo
[STAThread]
static void Main(string[] args)
{
int powerOfTwo = 1000;
int sum = 0;
// iterate through each (base 10) digit of 2^powerOfTwo, from right to left
for (int digit = 0; Math.Pow(10, digit) < Math.Pow(2, powerOfTwo); digit++)
{
// add next rightmost digit to sum
sum += (int)((Math.Pow(2, powerOfTwo) / Math.Pow(10, digit) % 10));
}
// write output to console, and save solution to clipboard
Console.Write("Power of two: {0} Sum of digits: {1}\n", powerOfTwo, sum);
Clipboard.SetText(sum.ToString());
Console.WriteLine("Answer copied to clipboard. Press any key to exit.");
Console.ReadKey();
}
}
}
Кажется, что отлично работает для powerOfTwo < 34. В моем калькуляторе не было значительных цифр выше, поэтому я не мог проверить более высокие полномочия. Но, отслеживая программу, похоже, что переполнения не происходит: количество вычисляемых цифр постепенно увеличивается с увеличением мощностиOFTwo = 1000, а сумма цифр также (в среднем) увеличивается с увеличением мощностиOfTwo.
Для фактического расчета, который я должен выполнить, я получаю вывод:
Мощность двух: 1000 Сумма цифр: 1189
Но 1189 - неправильный ответ. Что не так с моей программой? Я открыт для любой конструктивной критики.
Ответы
Ответ 1
Обычный int
не может помочь вам с таким большим количеством. Даже long
. Они никогда не предназначены для обработки таких огромных чисел. int
может хранить около 10 цифр (точный максимум: 2,147,483,647
) и long
примерно для 19 цифр (точный максимум: 9,223,372,036,854,775,807
). Тем не менее, быстрый расчет из встроенного калькулятора Windows говорит мне, что 2^1000
- это число более 300 цифр.
(боковое примечание: точное значение может быть получено из int.MAX_VALUE
и long.MAX_VALUE
соответственно)
Как вы хотите точную сумму цифр, даже float
или double
типы won ' т, потому что они хранят только значимые цифры за несколько десятков цифр. (7
digit для float, 15-16
цифры для double). Читайте здесь для получения дополнительной информации о представлении с плавающей запятой, двойной точности
Однако С# обеспечивает встроенную арифметику
BigInteger
для произвольной точности, которая должна соответствовать вашим потребностям (тестированию). т.е. может выполнять арифметику в любом количестве цифр (теоретически, конечно, на практике она ограничена памятью вашей физической машины и требует слишком много времени в зависимости от мощности вашего процессора)
Возвращаясь к вашему коду, я думаю, что проблема здесь
Math.Pow(2, powerOfTwo)
Это переполняет расчет. Ну, не совсем, но точность double
не точно отражает фактическое значение результата, как я уже сказал.
Ответ 2
Для вычисления значений таких больших чисел вам не только нужно быть хорошим программистом, но и хорошим математиком. Вот вам подсказка,
есть знакомая формула a x= e x ln a или, если вы предпочитаете, x= 10 x log a.
Более конкретно для вашей проблемы
2 1000 Найдите общий (базовый 10) лог 2 и умножьте его на 1000; это сила 10. Если вы получите что-то вроде 10 53.142 (53.142 = log 2 значение * 1000), что, скорее всего, будет - тогда это 10 53 x 10 0,142; просто оцените 10 0,142 и вы получите число от 1 до 10; и умножим это на 10 53. Но этот 10 53 не будет полезен, поскольку 53 нулевая сумма будет равна нулю.
Для вычисления журнала в С#
Math.Log(num, base);
Для большей точности вы можете использовать функцию Log и Pow Big Integer.
Теперь помощь в программировании для отдыха, я считаю, что у вас есть с вашей стороны.
Ответ 3
Решение, не использующее класс BigInteger, состоит в том, чтобы хранить каждую цифру в своем собственном int, а затем выполнять умножение вручную.
static void Problem16()
{
int[] digits = new int[350];
//we're doing multiplication so start with a value of 1
digits[0] = 1;
//2^1000 so we'll be multiplying 1000 times
for (int i = 0; i < 1000; i++)
{
//run down the entire array multiplying each digit by 2
for (int j = digits.Length - 2; j >= 0; j--)
{
//multiply
digits[j] *= 2;
//carry
digits[j + 1] += digits[j] / 10;
//reduce
digits[j] %= 10;
}
}
//now just collect the result
long result = 0;
for (int i = 0; i < digits.Length; i++)
{
result += digits[i];
}
Console.WriteLine(result);
Console.ReadKey();
}
Ответ 4
Я использовал побитовое смещение влево. Затем преобразование в массив и суммирование его элементов. Мой конечный результат - 1366, Не забудьте добавить ссылку на System.Numerics;
BigInteger i = 1;
i = i << 1000;
char[] myBigInt = i.ToString().ToCharArray();
long sum = long.Parse(myBigInt[0].ToString());
for (int a = 0; a < myBigInt.Length - 1; a++)
{
sum += long.Parse(myBigInt[a + 1].ToString());
}
Console.WriteLine(sum);
Ответ 5
так как вопрос С#, специфический с использованием bigInt, может выполнять задание. в java и python тоже работает, но в таких языках, как c и С++, где средство недоступно, вам нужно взять массив и сделать размножение. возьмите большую цифру в массиве и умножьте ее на 2. Это будет просто и поможет в улучшении вашего логического навыка. и приход к проекту Эйлера. есть проблема, в которой вам нужно найти 100! вы можете захотеть применить к нему ту же логику.
Ответ 6
Попробуйте использовать BigInteger type
, 2 ^ 100 закончится до очень большого числа, даже для двукратного обращения.
Ответ 7
BigInteger bi= new BigInteger("2");
bi=bi.pow(1000);
// System.out.println("Val:"+bi.toString());
String stringArr[]=bi.toString().split("");
int sum=0;
for (String string : stringArr)
{ if(!string.isEmpty()) sum+=Integer.parseInt(string); }
System.out.println("Sum:"+sum);
------------------------------------------------------------------------
output :=> Sum:1366
Ответ 8
Это не серьезный ответ - просто наблюдение.
Несмотря на то, что это хороший вызов, чтобы попытаться победить Project Euler, используя только один язык программирования, я считаю, что сайт нацелен на то, чтобы продвигать горизонты всех программистов, которые его пытаются. Другими словами, рассмотрите использование другого языка программирования.
Общее Lisp решение может быть прост как
(defun sum_digits (x)
(if (= x 0)
0
(+ (mod x 10) (sum_digits (truncate (/ x 10))))))
(print (sum_digits (expt 2 1000)))
Ответ 9
main()
{
char c[60];
int k=0;
while(k<=59)
{
c[k]='0';
k++;
}
c[59]='2';
int n=1;
while(n<=999)
{
k=0;
while(k<=59)
{
c[k]=(c[k]*2)-48;
k++;
}
k=0;
while(k<=59)
{
if(c[k]>57){ c[k-1]+=1;c[k]-=10; }
k++;
}
if(c[0]>57)
{
k=0;
while(k<=59)
{
c[k]=c[k]/2;
k++;
}
printf("%s",c);
exit(0);
}
n++;
}
printf("%s",c);
}
Ответ 10
Python очень просто вычислить это с помощью oneliner:
print sum(int(digit) for digit in str(2**1000))
или, альтернативно, с картой:
print sum(map(int,str(2**1000)))