心如止水

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

参考自:http://www.cnblogs.com/herbert/archive/2011/02/13/1953943.html

Project Euler problem 16

215 = 32768 and the sum of its digits is 3 + 2 + 7 + 6 + 8 = 26.

What is the sum of the digits of the number 21000?

计算 2 1000次方的所有数字的和?

这个设计大数乘方问题,通用的思路就是采用数组来分段处理大数,分段表示大数。下面的算法中,我采用的是万进制,用数组来存储数据。

原理如下:

先说计数方法:

比如

 2 26次方

num= 67108864

我们可以这样来写这个数:

6710 8864 

arr[0] = 6710, arr[1] = 8864

那么,arr数组看起来就象和67108864是一样的

看到这里你明白了吧?

我们可以分段表示一个非常大的数而不必考虑它的溢出,

而只用考虑段数是否大于一个数即可

举个例子:

上边,单段的最大值是9999,每段不溢出

那么,num就不会溢出

再一个乘法.

我们老祖宗给我们留下的算盘,很妙,

它其实就是最基本的计算机之一

我们算乘方时,

只用乘以一个数:

这样来列式子:

  123456790

                *2=

--------------

      246913580

 

:

123               456                   790

  *2=             *2=                   *2=

-----         -----             ------            

246               912                 (1)580(溢出)       第三段有溢出,加到上一段

-----       -----             --------

246             913                     580

 

呵呵,就这样,打算盘一样,进位.

最后是我自己(cutebear)用c#写的,测试通过:

        private static string BigNumberPow(int baseNumber, int power)
{
// Math.Log10(x^y) = y * Math.Log10(x).
// 估计结果有多少位。
double rawDigitCount = power * Math.Log10((double)baseNumber);
double digitCount = (int)(Math.Ceiling(rawDigitCount));
// 这里用万进制,即满一万进1,运算过程用数组来存放,数组中每一个的最大值是9999。
// 除以4,得到所需的数组的长度。
int arrayLength = (int)(Math.Ceiling((double)(digitCount / 4.0)));

int[] numbers = new int[arrayLength];
int jinweinumber = 0;
// 模拟人工运算,设置初始值。
numbers[arrayLength - 1] = baseNumber;
// 由于设置了初始值,所以需要乘以baseNumber共power -1次。
for (int j = 1; j < power; j++)
{
// 对每一段乘以baseNumber,注意进位的值要加到前一段。
for (int i = arrayLength - 1; i >= 0; i--)
{
if (numbers[i] == 0 && jinweinumber == 0)
continue;
numbers[i]
= numbers[i] * baseNumber;
numbers[i]
+= jinweinumber;
if (numbers[i] > 9999)
{
var quyu
= numbers[i] % 10000;
jinweinumber
= (numbers[i] - quyu) / 10000;
numbers[i]
= quyu;
}
else
jinweinumber
= 0;
}
}

StringBuilder result
= new StringBuilder();
for (int i = 0; i < arrayLength; i++)
{
// 不足四位的前面补0。
result.Append(numbers[i].ToString("0000"));
}

return result.ToString().TrimStart('0');
}

同理,下面是计算大数的阶乘:

private static string JieCh(int n)
{
// 使用万进制,每个数组元素四位,估计用来存计算结果所需数组的长度。
int arraylength = 50;
int[] numbers = new int[arraylength];
numbers[arraylength
- 1] = 1;
for (int j = 2; j <= n; j++)
{
int jinweinumber = 0;
for (int i = arraylength - 1; i >= 0; i--)
{
numbers[i]
*= j;
numbers[i]
+= jinweinumber;
if (numbers[i] > 9999)
{
var quyu
= numbers[i] % 10000;
jinweinumber
= (numbers[i] - quyu) / 10000;
numbers[i]
= quyu;
}
else
jinweinumber
= 0;
}
}
StringBuilder result
= new StringBuilder();
for (int i = 0; i < arraylength; i++)
{
result.Append(numbers[i].ToString(
"0000"));
}

return result.ToString().TrimStart('0');
}
posted on 2011-08-17 16:35  cutebear  阅读(1260)  评论(0编辑  收藏  举报