不使用 BigInt 计算 2^1000 之和

发布于 2024-09-08 21:57:44 字数 344 浏览 7 评论 0 原文

你们中的一些人可能会注意到这个问题是来自 问题 16 href="http://projecteuler.net/" rel="nofollow noreferrer">欧拉项目。我已经使用 C# 4.0 的新“bigInt”功能解决了这个问题,该功能相当简单,但也没有真正学习我应该学习的所有内容。我假设因为它是 2 ^ 1000 ,所以会有某种位移解决方案,但我无法弄清楚它到底是如何工作的。

有谁知道不使用bigint计算2^1000的方法吗?

As some of you may notice this question is problem 16 from Project Euler. I have solved it using the new "bigInt" feature of C# 4.0 which was fairly straightforward but which is also not really learning everything I should. I am assuming that since it is 2 ^ 1000 there would be some sort of bit shifting solutions but I can't figure out how exactly it would work.

Does anybody know a way to calculate 2^1000 without using bigint?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

烙印 2024-09-15 21:57:44

这个问题最难的部分不是计算(只是从 1 开始,然后加倍 1000 次),而是以十进制显示答案。考虑到这一点,您可能会发现在概念上更容易以某种形式的 BCD 表示形式(例如 base-1000)执行计算。然后执行 2 的长乘法一千次。这是一个Python解决方案:

def mul2(n):
    result = []
    carry = 0
    for i in n:
        i = i * 2 + carry
        carry = 0 if i < 1000 else 1
        result.append(i % 1000)
    if carry: result.append(1)
    return result

n = [1]
for _ in range(1000):
    n = mul2(n)

print ''.join('{0:03}'.format(i) for i in reversed(n)).lstrip('0')

The hardest part of this problem is not the computation (just start with 1 and double it 1000 times), but displaying the answer in decimal. With this in mind, you might find it conceptually easier to perform the computation in some form of BCD representation, such as base-1000. Then perform long multiplication by 2 a thousand times. Here's a Python solution:

def mul2(n):
    result = []
    carry = 0
    for i in n:
        i = i * 2 + carry
        carry = 0 if i < 1000 else 1
        result.append(i % 1000)
    if carry: result.append(1)
    return result

n = [1]
for _ in range(1000):
    n = mul2(n)

print ''.join('{0:03}'.format(i) for i in reversed(n)).lstrip('0')
哆兒滾 2024-09-15 21:57:44

这是在 python 中使用数字列表(或数组)来完成此操作的一种相当幼稚的方法

digits = [1]
for n in range(1000):
    newdigits = []
    carry = 0
    for digit in digits:
        s = 2*digit+carry
        carry = s/10
        s = s%10
        newdigits.append(s)
    if carry:
        newdigits.append(carry)
    digits = newdigits
print "".join(map(str,reversed(digits)))

Here is a rather naive way to do it in python just using a list(or array) of digits

digits = [1]
for n in range(1000):
    newdigits = []
    carry = 0
    for digit in digits:
        s = 2*digit+carry
        carry = s/10
        s = s%10
        newdigits.append(s)
    if carry:
        newdigits.append(carry)
    digits = newdigits
print "".join(map(str,reversed(digits)))
記柔刀 2024-09-15 21:57:44

您可以自己实现 BigInt,这可能会引入错误,并可能导致解决方案速度慢得多。典型的实现是自己手动执行数学运算(以每个数字为基础),使用一些高基数,例如基数 2^16 数字。

You could implmeent BigInt yourself, potentially introducing bugs and likely result in a much slower solution. A typical implementation is to manually perform the maths yourself (on a per digit basis), with some high base, such as base 2^16 numbers.

情感失落者 2024-09-15 21:57:44

问题实际上是 2^1000 到基数 10 的转换。一种简单的方法是实现某种任意长度的 BCD(二进制编码十进制)并计算 BCD 中的 2^1000。 250 字节的数组就足够了。然后你只需编写对任意长度的 BCD 数执行 *2 的方法并调用它 1000 次)。然后提取和求和数字就很容易了。

即使使用 C 等语言也很容易实现。

The problem is really conversion of 2^1000 to base 10. One easy way could be to implement some kind of BCD (Binary Coded Decimal) of arbitrary length and compute 2^1000 in BCD. An array of 250 bytes would be more than enough. Then you just have to write the method to perform *2 on a BCD number of arbitrary length and call it 1000 times). Then extracting and suming the digits is easy.

That's very easy to implement even in languages such as C.

沉默的熊 2024-09-15 21:57:44
class Program
{
    static void Main(string[] args)
    {
        double sum=0;
        for (int i = 1000; i <=1000; i++)
        {
            double pow = Math.Pow(2, i);
            string power = pow.ToString();
            for (int j = 0; j < power.Length; j++)
            {
                 sum = sum+pow % 10;
                 StringBuilder t = new StringBuilder(pow.ToString());
                 int len = t.Length;
                 if (len != 1)
                 {
                     t.Remove(len - 1, 1);
                 }
                 pow = Convert.ToDouble(t.ToString());
            }
             Console.WriteLine(sum);
                Console.WriteLine();

        }
    }
}
class Program
{
    static void Main(string[] args)
    {
        double sum=0;
        for (int i = 1000; i <=1000; i++)
        {
            double pow = Math.Pow(2, i);
            string power = pow.ToString();
            for (int j = 0; j < power.Length; j++)
            {
                 sum = sum+pow % 10;
                 StringBuilder t = new StringBuilder(pow.ToString());
                 int len = t.Length;
                 if (len != 1)
                 {
                     t.Remove(len - 1, 1);
                 }
                 pow = Convert.ToDouble(t.ToString());
            }
             Console.WriteLine(sum);
                Console.WriteLine();

        }
    }
}
最偏执的依靠 2024-09-15 21:57:44

好吧,

1 << 1000

更严肃地说,x 位整数最多可以容纳 1<。要实际计算 1<<1000,您需要一个 1000 位处理器(技术上是 1001 位,但现在谁在数)。由于这是不可行的,您唯一的选择就是模拟它(这就是 bigint 所做的)。

OK here goes:

1 << 1000

On a more serious note, the most you can hold in an x-bit integer is 1<<x-1. To actually calculate 1<<1000 you'd need a 1000-bit processor (technically 1001-bit, but who's counting at this point). Since that's not feasable, your only choice is to emulate it (and that's what bigint does).

苹果你个爱泡泡 2024-09-15 21:57:44

实际上没有什么可计算的:2^1000 = (1000...[994]...000)[Base2]。已经是‘结果’了。

如果您想知道如何存储它,您的机器不具备存储其确切值的精度。因此它要么是 BigInt,要么是双精度近似值 Math.Pow(2, 1000)。

编辑:我现在看到您从评论中只想要数字之和。请参阅解决方案之一。

There's nothing to calculate actually: 2^1000 = (1000...[994]...000)[Base2]. It's a 'result' already.

If you want to know how to store it, you machine doesn't have the precision to store its exact value. So it's either a BigInt, or the double approximate value Math.Pow(2, 1000).

Edit: I see now you from comments just want the sum of the digits. See one of the solutions.

相权↑美人 2024-09-15 21:57:44

我将尝试在不给出太多代码的情况下回答...

1)使用字符串来保存乘积

2)执行长乘法(就像您在学校所做的那样)

Prod = "1"
for n = 1 to 1000
        carry = 0
        newprod = ""
        for i = strlen(prod) - 1 to 0 step - 1
                digit = int(prod[i])
                p = digit * 2 + carry
                newprod = (p % 10) & newprod // append
                carry = p / 10
        next
        if( carry > 0) newprod = carry & newprod
        prod = newprod
next

在这里打印产品

记事本编码...所以如果有人发现错误,请纠正它们。

I'll try and answer without giving away much code...

1) Use a String to hold the Product

2) Perform Long Multiplication (like you did in school)

Prod = "1"
for n = 1 to 1000
        carry = 0
        newprod = ""
        for i = strlen(prod) - 1 to 0 step - 1
                digit = int(prod[i])
                p = digit * 2 + carry
                newprod = (p % 10) & newprod // append
                carry = p / 10
        next
        if( carry > 0) newprod = carry & newprod
        prod = newprod
next

print prod

Notepad-Coding here...so if anyone finds bugs please correct them.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文