I have this code
我有这个代码
#include <iostream>
using namespace std;
int main(int argc,char **argv) {
unsigned long long num1 = 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999995LL;
unsigned long long num2 = 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999996LL;
unsigned long long num3 = 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999997LL;
unsigned long long num4 = 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999998LL;
unsigned long long num5 = 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999LL;
cout << (unsigned long long)(num1 * num2 * num3 * num4 * num5) << endl;
return 0;
}
As you can see the numbers are enormous, but when I do the math there I get this: 18446744073709551496
你可以看到数字是巨大的,但当我在那里做数学时我得到这个:18446744073709551496
At compile time I get these warnings:
在编译时我得到这些警告:
warning: integer constant is too large for its type|
In function `int main(int, char**)':|
warning: this decimal constant is unsigned only in ISO C90|
...
7 个解决方案
#1
20
Your result is larger than the long long type - you need to look at a BigInteger or arbitrary precision library, something like gmp
您的结果大于long long类型 - 您需要查看BigInteger或任意精度库,例如gmp
#2
6
Those numbers won't fit into any C++ data types. If you just want to print them, store the numbers in a string. If you want to do math on it, find an arbitrary precision math library and use that.
这些数字不适合任何C ++数据类型。如果您只想打印它们,请将数字存储在字符串中。如果你想对它进行数学运算,找一个任意精度的数学库并使用它。
#3
3
If you want literals this big in your code, you'll have to enter them as string literals and load them into a BigInt class of some sort. There's no way to express integer literals that big in source code right now (although C++0x will hopefully address that shortfall).
如果你想在你的代码中使用这么大的文字,你必须将它们作为字符串文字输入并将它们加载到某种类型的BigInt类中。现在没有办法表达源代码中的大整数文字(尽管C ++ 0x有望解决这个不足)。
If you're using the BigInteger library, take a look at the stringToBigUnsigned
function in BigIntegerUtils.hh
for building a big integer from a string.
如果您正在使用BigInteger库,请查看BigIntegerUtils.hh中的stringToBigUnsigned函数,以便从字符串构建一个大整数。
#include "BigUnsigned.hh"
#include "BigIntegerUtils.hh"
BigUnsigned num1 = stringToBigUnsigned (
"99999999999999999999999999999999999999999999999999999999999999999999999999999999"
"99999999999999999999999999999999999999999999999999999999999999999999999999999999"
"99999999999999999999999999999999999999999999999999999999999999999999999999999999"
"99999999999999999999999999999999999999999999999999999999999999999999999999999999"
"99999999999999999999999999999999999999999999999999999999999999999999999999999999"
"99999999999999999999999999999999999999999999999999999999999999999999999999999999"
"99999999999999999999999999999999999999999999999999999999999999999999999999999999"
"99999999999999999999999999999999999999999999999999999999999999999999999999999999"
"99999999999999999999999999999999999999999999999999999999999999999999999999999999"
"99999999999999999999999999999999999999999999999999999999999999999999999999999999"
"99999999999999999999999999999999999999999999999999999999999999999999999999999999"
"99999999999999999999999999999999999999999999999999999999999999999999999999999999"
"99999999999999999999999999999999999995"
);
#4
3
What is it you are trying to do? Do you understand the basics of binary and decimal numbers? Why 8 bits only holds the values 0 to 255, 12 bits 0 - 4095, etc? How many bits does it take to hold the number you are interested in? Or better, how big of a number are you interested in creating? And are you using 9s to make the number bigger? What about hex 0xF... instead? If you want the biggest unsigned number (within one of the standard integer types) why not:
你想做什么?你了解二进制和十进制数字的基础知识吗?为什么8位只保存值0到255,12位0-4095等?保留您感兴趣的号码需要多少位?或者更好的是,你有多大兴趣创造?你使用9s来增加数字吗?那么十六进制0xF ......呢?如果您想要最大的无符号数(在一个标准整数类型中),为什么不:
unsigned long long a,b;
unsigned long long a,b;
a = -1; //which just seems wrong mixing signed and unsigned but it is valid, the number is converted to unsigned before storing
a = -1; //这似乎是错误的混合有符号和无符号但它是有效的,数字在存储之前转换为无符号
b = 0; b--; //does the same thing as above
b = 0; b--; //做与上面相同的事情
Do you really need precision at that level? You realize that multiplies can require a result twice the size of each operand? 0xFF * 0xFF = 0xFE01, if in this case you were using 8 bit integers you could not do the math. It only gets worse as you continue to multiply 0xFF * 0xFF * 0xFF = 0xFD02FF.
你真的需要那个级别的精度吗?您意识到乘法可能需要两倍于每个操作数的结果? 0xFF * 0xFF = 0xFE01,如果在这种情况下你使用的是8位整数,则无法进行数学计算。随着你继续乘以0xFF * 0xFF * 0xFF = 0xFD02FF,情况会变得更糟。
What are trying to do?
试图做什么?
Seeing your response:
看到你的回复:
I have not seen euler number 8 before. Sounds like a good interview question as it only takes a few lines of code to solve.
我之前没见过8号欧拉。听起来像一个很好的面试问题,因为它只需要几行代码来解决。
Your other response:
你的其他回复:
Numbers...
Likely because we have 10 fingers (and perhaps 10 toes) we grow up with "base 10". Our clocks are base 60 for the most part but it has been mixed with base 10 to make it more confusing. Anyway, base 10, means for each number placeholder you have one of 10 unique digits, when you reach the maximum in that place you roll over to the next place. This is all elementary school stuff.
可能因为我们有10个手指(也许是10个脚趾),我们长大了“基础10”。我们的时钟基本上是60的基础,但它与基数10混合使其更加混乱。无论如何,基数10,表示每个数字占位符,您有10个唯一数字之一,当您达到该位置的最大值时,您将滚动到下一个位置。这是所有小学的东西。
000
001
002
003
...
008
009
010
011
012
...
000 001 002 003 ... 008 009 010 011 012 ...
See how the right most digit has 10 symbols (0,1,2,3,4,5,6,7,8,9) and when it reaches the last symbol it starts over and the one to the left of it increments by one. This rule is true for all base numbering systems.
看看最右边的数字如何有10个符号(0,1,2,3,4,5,6,7,8,9),当它到达最后一个符号时,它重新开始,它的左边一个增加一。所有基本编号系统都适用此规则。
It is true for base 2 except there are only two symbols, 0 and 1
除了只有两个符号0和1之外,基数2都是如此
000
001
010
011
100
101
...
000 001 010 011 100 101 ...
Same is true for octal, but 8 symbols (0,1,2,3,4,5,6,7)
八进制也是如此,但是8个符号(0,1,2,3,4,5,6,7)
000
001
002
003
004
005
006
007
010
011
012
013
...
000 001 002 003 004 005 006 007 010 011 012 013 ...
And the same is true for hexadecimal, 16 symbols(0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f)
对于十六进制,16个符号(0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f)也是如此
000
001
002
003
004
005
006
007
008
009
00a
00b
00c
00d
00e
00f
010
011
012
013
...
000 001 002 003 004 005 006 007 008 009 00a 00b 00c 00d 00e 00f 010 011 012 013 ...
I was about to go into the whys of using binary over other bases (like 10) in computers. The bottom line it is easy to have two states on or off, or high and low. Two states is like two symbols 1 and 0 in base 2. Trying to keep electronics tuned to more than two states within the available voltage is tough, at least it used to be, keeping it near zero volts or above some small number of volts is relatively easy, so digital electronics use two states, binary.
我打算在计算机中使用二进制代替其他基础(如10)。底线很容易打开或关闭两个状态,或者高低。两个状态就像基数2中的两个符号1和0.试图将电子器件调整到可用电压范围内的两个以上状态是困难的,至少过去是这样,保持接近零伏特或高于某些少量的电压是相对容易,所以数字电子使用两种状态,二进制。
Even a simple task for a human in binary is long winded, simple second grade math is still a lot of ones and zeros. So octal became popular because it allowed you to think in groups of three bits and you could use symbols we are familiar with as numbers 0,1,2,3,4,5,6,7. But groups of four which is another power of 2, gives the humans a lot more mental computing power than octal, hex is based on 4 bits which is also a power of 2. We had to add more symbols to the 10 we borrowed from the traditial arabic base 10, so the first 6 of the alphabet was used. Octal is rarely if ever used, you can tell someones age if they think octal instead of hex. (I am from the hex generation but have worked with those from the octal generation that struggle with hex because they cannot get from octal to binary to hex in their mind).
即使是二元人类的简单任务也是冗长的,简单的二年级数学仍然是很多的零和零。所以八进制变得流行,因为它允许你以三位组的形式思考,你可以使用我们熟悉的符号作为数字0,1,2,3,4,5,6,7。但是四个一组是2的另一个幂,给人类比八进制更多的心算计算能力,十六进制基于4位,这也是2的幂。我们不得不在我们借用的10中添加更多的符号。传统的阿拉伯语基础10,所以使用了前6个字母表。如果使用Octal很少,如果他们认为八角形而不是十六进制,你可以告诉某人年龄。 (我来自十六代,但是与那些与十六进制斗争的八代人合作,因为他们无法从八进制到二进制到十六进制)。
Base 10 in a computer is like the average human thinking in hex. computers dont do base 10 (well for lazy humans they used to do bcd), they do base 2. The decimal number 1234 in a computer is really 0x4D2 or 0b010011010010. That is as a value, say you want to add 1234 plus some other number you need that value which has nothing to do with the symbos 1, 2, 3, and 4. But to post this answer on * we dont use the number we use ASCII, so 1234 in ascii is 0x31, 0x32, 0x33, 0x34, which is important to know for your euler solution assuming the 1000 digit number was provided as an ascii string, which it would have to be or you would have to convert it from binary to ascii since the problem is a base 10 problem and not base 2 by definition.
计算机中的基础10就像十六进制中的普通人类思维。计算机不做基数10(对于他们曾经做过bcd的懒人),他们做基数2.计算机中的十进制数1234实际上是0x4D2或0b010011010010。这是一个值,比如你想要添加1234加上你需要的其他数字,这与symbos 1,2,3和4无关。但是要在*上发布这个答案我们不使用数字我们使用ASCII,所以ascii中的1234是0x31,0x32,0x33,0x34,这对于你的euler解决方案很重要,假设1000位数字是作为ascii字符串提供的,它必须是或者你必须转换它从二进制到ascii,因为问题是基本问题,而不是定义基数2。
So back to what I had asked. Say you had 4 bits of memory to store a number, how big of a number could you store? If you think base 10 only you might think that number is a 9, because you are trained to think of using the biggest symbol in each storage location, 99999 is the biggest number if you have 5 storage locations in base 10. Back to four bits though, the biggest symbol for a single bit is 1, put that number in each storage location you get 1111 (four ones). Just by looking at those four ones you should be able to in your mind easily see the octal and hex version of that same number 17 octal or F hex. To see decimal takes math, or in this case memorization, that number is 15 decimal. So the biggest four bit number you can have is 0xF or 15 not 9. What about an 8 bit number? 0xFF or 255 (2 to the 8th power minus one). Biggest 16 bit number? 65535, etc.
回到我的要求。假设您有4位内存来存储一个数字,您可以存储多少个数字?如果你认为10号基数你可能认为这个数字是9,因为你被训练想到在每个存储位置使用最大的符号,如果你在基数10中有5个存储位置,99999是最大的数字。回到4位但是,单个位的最大符号是1,将该数字放在每个存储位置1111(四个)。只要查看这四个,您就可以在脑海中轻松看到相同数字17八进制或十六进制的八进制和十六进制版本。要查看十进制需要数学,或者在这种情况下记忆,该数字是15十进制。所以你可以拥有的最大四位数是0xF或15而不是9. 8位数怎么样? 0xFF或255(2到8次幂减去1)。最大的16位数? 65535等
So when I ask how many bits are you trying to use this is what I mean. Look at this number 99999. Again base 10 you would think that is the biggest number, but to a computer it is only part way there, 99999 decimal is 0x1869F, which takes 17 bits of memory to store, the biggest 17 bit number you can store is 0x1FFFF which is 131071 which is a bit bigger than 99999. So when you want to think big numbers and math on a computer you have to think binary (or hex).
所以,当我问你要使用多少位时,这就是我的意思。看看这个数字99999.再次基数10,你会认为这是最大的数字,但对于计算机它只是那里的一部分,99999十进制是0x1869F,需要17位内存来存储,最大的17位数你可以store是0x1FFFF,这是131071,比99999大一点。所以当你想在计算机上想大数字和数学时,你必须考虑二进制(或十六进制)。
Originally you were doing multiplications, which is still part of the euler problem, but what was I was asking about was related to precision and bit storage. Here are some fundamentals, and I wont get into it but you can see why we rely on floating point units in computers.
最初你正在做乘法,这仍然是欧拉问题的一部分,但我所询问的是与精度和位存储有关。这里有一些基础知识,我不会介绍它,但你可以看到为什么我们依赖计算机中的浮点单元。
Take the largest 4 bit number 1111(binary), which is 15 decimal. Add that with the largest four bit number and you get 15+15 = 30 = 0x1E or 11110 binary. So to add two four bit numbers you need five bits to hold your answer. Computers keep a "carry" bit for this extra bit. Essentially the add/subtract integer math functions in the computer allow you to have N+1 bits. So if it is an 32 bit computer you basically have 33 bits for add/sub math.
取最大4位数1111(二进制),即十进制15。添加具有最大四位数的那个,你得到15 + 15 = 30 = 0x1E或11110二进制。因此,要添加两个四位数字,您需要五位来保持答案。计算机为这个额外的位保留一个“进位”位。本质上,计算机中的加/减整数数学函数允许您有N + 1位。因此,如果它是32位计算机,你基本上有33位用于加/子数学。
The problem is multiply and divide, which even today many processors do not support (yes many have no fpu and only do add and subtract, sometimes multiply, but divide is rare. Multiply and divide take a lot of electronics the trade off is you can do them with adds and subtracts in software). Take the worst case multiply for a four bit system 1111 * 1111 = 11100001 so it takes 8 bits to store the result of a 4 bit multiply, you will quickly find that if you had a 4 bit system MOST of the multiplies you want to do will result a number that cannot be stored in 4 bits. So when I saw you taking 64 bit integers (the unsigned long long is often 64 bits) and multiplying four times, that means you need 64*5 or a 320 bit integer to store your answer, you were trying to put that answer in a 64 big result, which quite often, depending on the compiler and computer will happily do and will truncate the upper bits leaving you with the lower 64 bits of the result which can easily look smaller than any of your operands, which is what I had thought you might have done at first.
问题是乘法和除法,即使在今天许多处理器也不支持(是的,许多处理器没有fpu,只能加减,有时会成倍增加,但除法很少。乘法和除法需要很多电子设备,你需要权衡利弊在软件中添加和减少它们。对于四位系统1111 * 1111 = 11100001采用最坏情况乘法,因此需要8位来存储4位乘法的结果,如果你有一个4位系统MOST,那么你很快就会发现将产生一个无法以4位存储的数字。因此,当我看到你采用64位整数(无符号长整数通常是64位)并乘以四次,这意味着你需要64 * 5或320位整数来存储你的答案,你试图把这个答案放在一个64大结果,这通常取决于编译器和计算机将很乐意做,并将截断高位,留下你的结果的低64位,这可能很容易看起来比你的任何操作数小,这是我所想的你可能一开始就做过。
Floating point is not much more than scientific notation but in binary, if you wanted to multiply the number 1234 and 5678 using scientific notation you would take 1.234*10^3 times 5.678*10^3 and get 7.007*10^6. You keep your precision and are able to represent a wider range of numbers. I wont get into how this works in binary. But it doesnt work for your original question.
浮点数不仅仅是科学记数法,而是二进制数,如果你想用科学计数法乘以数字1234和5678,你需要1.234 * 10 ^ 3倍5.678 * 10 ^ 3得到7.007 * 10 ^ 6。您保持精确度并能够代表更广泛的数字。我不会深入研究二进制文件的工作原理。但它对你原来的问题不起作用。
Ahh, the last thing to clarify what I was doing in my question/response. Negative integers in binary. Because of the relationships between addition and subtraction and base systems you can play some tricks. Say I wanted to subtract 1 from the number 7(decimal) using binary. Well there is no such thing as a subtract circuit, you instead add a negative number so instead of 7 - 1 it is really 7 + (-1), it makes a difference:
啊,最后要澄清我在问题/回答中做了什么。二进制中的负整数。由于加法和减法以及基本系统之间的关系,你可以玩一些技巧。假设我想使用二进制从数字7(十进制)中减去1。那么没有减法电路这样的东西,你改为添加一个负数,而不是7 - 1,它实际上是7 +( - 1),它有所不同:
0111 + ???? = 0110
0111 + ???? = 0110
What number could you add to 7 to get 6...in binary?
你可以在7中加入6来获得6 ...二进制数?
0111 + 1111 = 0110
0111 + 1111 = 0110
Negative numbers in binary are called "twos complement", long story short the answer is "invert and add 1". How do you represent minus 1 in binary? take plus one 0001 then invert it meaning make the ones zeros and the zeros ones (also known as ones complement) 1110 then add one 1111. Minus one is a special number in computers (well everywhere) as no matter how many bits you have it is represented as all ones. So when you see someone do this:
二进制中的负数称为“二进制补码”,长话短说答案是“反转并加1”。你如何在二进制中表示减1?加上一个0001然后反转它意味着使零和零(也称为补码)1110然后添加一个1111.减1是计算机中的特殊数字(无处不在),无论你有多少位表示为所有。所以当你看到有人这样做时:
unsigned char a;
unsigned char a;
a = -1;
a = -1;
The compiler first looks at that -1 and thinks ...11111(binary) then it looks at the equals sign and the other side, oh, you want a to be all ones, it sees that you have a signed integer and an unsigned but the conversion is to just move the bits over so you are saying above that you want a = 0xFF; (assuming an 8 bit unsigned char).
编译器首先查看-1并认为... 11111(二进制)然后它查看等号和另一侧,哦,你想要一个是全部的,它看到你有一个有符号整数和一个无符号但转换只是移动位,所以你在上面说你想要一个= 0xFF; (假设8位无符号字符)。
Some compilers may complain that you are trying to store a negative number in an unsigned number. Other compilers will look at that -1 and see it as a 32 bit or these days maybe 64 bit signed integer constant and then when it evaluates the equals into an 8 bit unsigned you will get a warning that you cannot store -1 in a signed or unsigned char without a typecast. But if you do this:
某些编译器可能会抱怨您正在尝试将负数存储在无符号数字中。其他编译器将查看-1并将其视为32位或这些天可能是64位有符号整数常量,然后当它将等于8位无符号时,您将收到一条警告,指出您无法在签名中存储-1或没有类型转换的unsigned char。但是如果你这样做:
a = 0; a--;
a = 0;一个 - ;
All compilers will like that. and wont complain, it just burns computing cycles at runtime instead of compile time.
所有编译器都会喜欢这样。并且不会抱怨,它只是在运行时而不是编译时烧掉计算周期。
Now somewhere a friend told me of a book that does binary math serially. For example to negate a number, usually you do the invert and ad one trick, but with pencil and paper some may tell you the other trick. Starting from the right copy the zeros up to and including the first 1 then invert after that, so minus 2
现在某个朋友告诉我一本连续二进制数学的书。例如,为了否定一个数字,通常你会做反转和广告一招,但是用铅笔和纸一些可能会告诉你另一个技巧。从正确的复制开始,将零复制到包括第一个1,然后在此之后反转,因此减去2
0010
1110
Starting from the right copy the 0 then the first one, then invert the remaining bits as you go left.
从右边开始复制0然后从第一个复制,然后在向左移动时反转剩余的位。
minus 6
0110
1010
minus 4
0100
1100
Supposedly there are tricks to do add and subtract (well duh, those are easy) but also multiply and divide. If you do them serially then you can do infinitely long math in binary with the same alu. If you were to know how to do that you could implement that in software and your original question of multiplying big constants (with the assumption of retaining all the precision) is trivial on any computer.
据说有添加和减去的技巧(好吧,那些很容易),但也是乘法和除法。如果你按顺序执行它们,那么你可以使用相同的alu进行无限长的二进制数学运算。如果你知道如何做到这一点,你可以在软件中实现它,你的原始问题是乘以大常数(假设保留所有精度)在任何计算机上都是微不足道的。
#5
1
The answer that you got, 18446744073709551496, is due to your 999...9s being truncated when assigned to a long long, plus the multiple operations overflowing. Its deterministic, but effectively just a random collection of bits.
你得到的答案,18446744073709551496,是由于你的999 ... 9s被分配到一个很长的长,加上多个操作溢出。它的确定性,但实际上只是随机的比特集合。
#6
0
unsigned int represents a system word. Today, that word will max out at either 2^32 -1 or 2^64 - 1, depending on whether your system is 32 bit or 64 bit. You're hitting the cap.
unsigned int表示系统字。今天,根据您的系统是32位还是64位,该字最大值为2 ^ 32 -1或2 ^ 64-1。你打算上限。
You have to write a bignum class or use one off the 'net.
你必须写一个bignum类或使用'net。
Why are you doing this problem anyway?
你为什么要这样做呢?
#7
0
The numbers can't fit in unsigned long long
range so either you could use GMP library or use string to represent big numbers like I did for calculating factorial of number like 50:
这些数字不适合无符号长的长距离,所以要么你可以使用GMP库,要么使用字符串代表大数字,就像我用来计算50的数字阶乘一样:
#include <cmath>
#include <iostream>
using namespace std;
int main()
{
unsigned int nd, nz;
unsigned char *ca;
unsigned int j, n=50, q, temp;
int i;
double p;
p = 0.0;
for(j = 2; j <= n; j++)
{
p += log10((double)j);
}
nd = (int)p + 1;
ca = new unsigned char[nd+1];
if (!ca)
{
cout << "Could not allocate memory!!!";
exit(0);
}
for (i = 1; (unsigned)i < nd; i++)
{
ca[i] = 0;
}
ca[0] = 1;
p = 0.0;
for (j = 2; j <= n; j++)
{
p += log10((double)j);
nz = (int)p + 1;
q = 0;
for (i = 0;(unsigned) i <= nz; i++)
{
temp = (ca[i] * j) + q;
q = (temp / 10);
ca[i] = (char)(temp % 10);
}
}
cout << "\nThe Factorial of " << n << " is: ";
for( i = nd - 1; i >= 0; i--)
{
cout << (int)ca[i];
}
// delete []ca;
return 0;
}
#1
20
Your result is larger than the long long type - you need to look at a BigInteger or arbitrary precision library, something like gmp
您的结果大于long long类型 - 您需要查看BigInteger或任意精度库,例如gmp
#2
6
Those numbers won't fit into any C++ data types. If you just want to print them, store the numbers in a string. If you want to do math on it, find an arbitrary precision math library and use that.
这些数字不适合任何C ++数据类型。如果您只想打印它们,请将数字存储在字符串中。如果你想对它进行数学运算,找一个任意精度的数学库并使用它。
#3
3
If you want literals this big in your code, you'll have to enter them as string literals and load them into a BigInt class of some sort. There's no way to express integer literals that big in source code right now (although C++0x will hopefully address that shortfall).
如果你想在你的代码中使用这么大的文字,你必须将它们作为字符串文字输入并将它们加载到某种类型的BigInt类中。现在没有办法表达源代码中的大整数文字(尽管C ++ 0x有望解决这个不足)。
If you're using the BigInteger library, take a look at the stringToBigUnsigned
function in BigIntegerUtils.hh
for building a big integer from a string.
如果您正在使用BigInteger库,请查看BigIntegerUtils.hh中的stringToBigUnsigned函数,以便从字符串构建一个大整数。
#include "BigUnsigned.hh"
#include "BigIntegerUtils.hh"
BigUnsigned num1 = stringToBigUnsigned (
"99999999999999999999999999999999999999999999999999999999999999999999999999999999"
"99999999999999999999999999999999999999999999999999999999999999999999999999999999"
"99999999999999999999999999999999999999999999999999999999999999999999999999999999"
"99999999999999999999999999999999999999999999999999999999999999999999999999999999"
"99999999999999999999999999999999999999999999999999999999999999999999999999999999"
"99999999999999999999999999999999999999999999999999999999999999999999999999999999"
"99999999999999999999999999999999999999999999999999999999999999999999999999999999"
"99999999999999999999999999999999999999999999999999999999999999999999999999999999"
"99999999999999999999999999999999999999999999999999999999999999999999999999999999"
"99999999999999999999999999999999999999999999999999999999999999999999999999999999"
"99999999999999999999999999999999999999999999999999999999999999999999999999999999"
"99999999999999999999999999999999999999999999999999999999999999999999999999999999"
"99999999999999999999999999999999999995"
);
#4
3
What is it you are trying to do? Do you understand the basics of binary and decimal numbers? Why 8 bits only holds the values 0 to 255, 12 bits 0 - 4095, etc? How many bits does it take to hold the number you are interested in? Or better, how big of a number are you interested in creating? And are you using 9s to make the number bigger? What about hex 0xF... instead? If you want the biggest unsigned number (within one of the standard integer types) why not:
你想做什么?你了解二进制和十进制数字的基础知识吗?为什么8位只保存值0到255,12位0-4095等?保留您感兴趣的号码需要多少位?或者更好的是,你有多大兴趣创造?你使用9s来增加数字吗?那么十六进制0xF ......呢?如果您想要最大的无符号数(在一个标准整数类型中),为什么不:
unsigned long long a,b;
unsigned long long a,b;
a = -1; //which just seems wrong mixing signed and unsigned but it is valid, the number is converted to unsigned before storing
a = -1; //这似乎是错误的混合有符号和无符号但它是有效的,数字在存储之前转换为无符号
b = 0; b--; //does the same thing as above
b = 0; b--; //做与上面相同的事情
Do you really need precision at that level? You realize that multiplies can require a result twice the size of each operand? 0xFF * 0xFF = 0xFE01, if in this case you were using 8 bit integers you could not do the math. It only gets worse as you continue to multiply 0xFF * 0xFF * 0xFF = 0xFD02FF.
你真的需要那个级别的精度吗?您意识到乘法可能需要两倍于每个操作数的结果? 0xFF * 0xFF = 0xFE01,如果在这种情况下你使用的是8位整数,则无法进行数学计算。随着你继续乘以0xFF * 0xFF * 0xFF = 0xFD02FF,情况会变得更糟。
What are trying to do?
试图做什么?
Seeing your response:
看到你的回复:
I have not seen euler number 8 before. Sounds like a good interview question as it only takes a few lines of code to solve.
我之前没见过8号欧拉。听起来像一个很好的面试问题,因为它只需要几行代码来解决。
Your other response:
你的其他回复:
Numbers...
Likely because we have 10 fingers (and perhaps 10 toes) we grow up with "base 10". Our clocks are base 60 for the most part but it has been mixed with base 10 to make it more confusing. Anyway, base 10, means for each number placeholder you have one of 10 unique digits, when you reach the maximum in that place you roll over to the next place. This is all elementary school stuff.
可能因为我们有10个手指(也许是10个脚趾),我们长大了“基础10”。我们的时钟基本上是60的基础,但它与基数10混合使其更加混乱。无论如何,基数10,表示每个数字占位符,您有10个唯一数字之一,当您达到该位置的最大值时,您将滚动到下一个位置。这是所有小学的东西。
000
001
002
003
...
008
009
010
011
012
...
000 001 002 003 ... 008 009 010 011 012 ...
See how the right most digit has 10 symbols (0,1,2,3,4,5,6,7,8,9) and when it reaches the last symbol it starts over and the one to the left of it increments by one. This rule is true for all base numbering systems.
看看最右边的数字如何有10个符号(0,1,2,3,4,5,6,7,8,9),当它到达最后一个符号时,它重新开始,它的左边一个增加一。所有基本编号系统都适用此规则。
It is true for base 2 except there are only two symbols, 0 and 1
除了只有两个符号0和1之外,基数2都是如此
000
001
010
011
100
101
...
000 001 010 011 100 101 ...
Same is true for octal, but 8 symbols (0,1,2,3,4,5,6,7)
八进制也是如此,但是8个符号(0,1,2,3,4,5,6,7)
000
001
002
003
004
005
006
007
010
011
012
013
...
000 001 002 003 004 005 006 007 010 011 012 013 ...
And the same is true for hexadecimal, 16 symbols(0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f)
对于十六进制,16个符号(0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f)也是如此
000
001
002
003
004
005
006
007
008
009
00a
00b
00c
00d
00e
00f
010
011
012
013
...
000 001 002 003 004 005 006 007 008 009 00a 00b 00c 00d 00e 00f 010 011 012 013 ...
I was about to go into the whys of using binary over other bases (like 10) in computers. The bottom line it is easy to have two states on or off, or high and low. Two states is like two symbols 1 and 0 in base 2. Trying to keep electronics tuned to more than two states within the available voltage is tough, at least it used to be, keeping it near zero volts or above some small number of volts is relatively easy, so digital electronics use two states, binary.
我打算在计算机中使用二进制代替其他基础(如10)。底线很容易打开或关闭两个状态,或者高低。两个状态就像基数2中的两个符号1和0.试图将电子器件调整到可用电压范围内的两个以上状态是困难的,至少过去是这样,保持接近零伏特或高于某些少量的电压是相对容易,所以数字电子使用两种状态,二进制。
Even a simple task for a human in binary is long winded, simple second grade math is still a lot of ones and zeros. So octal became popular because it allowed you to think in groups of three bits and you could use symbols we are familiar with as numbers 0,1,2,3,4,5,6,7. But groups of four which is another power of 2, gives the humans a lot more mental computing power than octal, hex is based on 4 bits which is also a power of 2. We had to add more symbols to the 10 we borrowed from the traditial arabic base 10, so the first 6 of the alphabet was used. Octal is rarely if ever used, you can tell someones age if they think octal instead of hex. (I am from the hex generation but have worked with those from the octal generation that struggle with hex because they cannot get from octal to binary to hex in their mind).
即使是二元人类的简单任务也是冗长的,简单的二年级数学仍然是很多的零和零。所以八进制变得流行,因为它允许你以三位组的形式思考,你可以使用我们熟悉的符号作为数字0,1,2,3,4,5,6,7。但是四个一组是2的另一个幂,给人类比八进制更多的心算计算能力,十六进制基于4位,这也是2的幂。我们不得不在我们借用的10中添加更多的符号。传统的阿拉伯语基础10,所以使用了前6个字母表。如果使用Octal很少,如果他们认为八角形而不是十六进制,你可以告诉某人年龄。 (我来自十六代,但是与那些与十六进制斗争的八代人合作,因为他们无法从八进制到二进制到十六进制)。
Base 10 in a computer is like the average human thinking in hex. computers dont do base 10 (well for lazy humans they used to do bcd), they do base 2. The decimal number 1234 in a computer is really 0x4D2 or 0b010011010010. That is as a value, say you want to add 1234 plus some other number you need that value which has nothing to do with the symbos 1, 2, 3, and 4. But to post this answer on * we dont use the number we use ASCII, so 1234 in ascii is 0x31, 0x32, 0x33, 0x34, which is important to know for your euler solution assuming the 1000 digit number was provided as an ascii string, which it would have to be or you would have to convert it from binary to ascii since the problem is a base 10 problem and not base 2 by definition.
计算机中的基础10就像十六进制中的普通人类思维。计算机不做基数10(对于他们曾经做过bcd的懒人),他们做基数2.计算机中的十进制数1234实际上是0x4D2或0b010011010010。这是一个值,比如你想要添加1234加上你需要的其他数字,这与symbos 1,2,3和4无关。但是要在*上发布这个答案我们不使用数字我们使用ASCII,所以ascii中的1234是0x31,0x32,0x33,0x34,这对于你的euler解决方案很重要,假设1000位数字是作为ascii字符串提供的,它必须是或者你必须转换它从二进制到ascii,因为问题是基本问题,而不是定义基数2。
So back to what I had asked. Say you had 4 bits of memory to store a number, how big of a number could you store? If you think base 10 only you might think that number is a 9, because you are trained to think of using the biggest symbol in each storage location, 99999 is the biggest number if you have 5 storage locations in base 10. Back to four bits though, the biggest symbol for a single bit is 1, put that number in each storage location you get 1111 (four ones). Just by looking at those four ones you should be able to in your mind easily see the octal and hex version of that same number 17 octal or F hex. To see decimal takes math, or in this case memorization, that number is 15 decimal. So the biggest four bit number you can have is 0xF or 15 not 9. What about an 8 bit number? 0xFF or 255 (2 to the 8th power minus one). Biggest 16 bit number? 65535, etc.
回到我的要求。假设您有4位内存来存储一个数字,您可以存储多少个数字?如果你认为10号基数你可能认为这个数字是9,因为你被训练想到在每个存储位置使用最大的符号,如果你在基数10中有5个存储位置,99999是最大的数字。回到4位但是,单个位的最大符号是1,将该数字放在每个存储位置1111(四个)。只要查看这四个,您就可以在脑海中轻松看到相同数字17八进制或十六进制的八进制和十六进制版本。要查看十进制需要数学,或者在这种情况下记忆,该数字是15十进制。所以你可以拥有的最大四位数是0xF或15而不是9. 8位数怎么样? 0xFF或255(2到8次幂减去1)。最大的16位数? 65535等
So when I ask how many bits are you trying to use this is what I mean. Look at this number 99999. Again base 10 you would think that is the biggest number, but to a computer it is only part way there, 99999 decimal is 0x1869F, which takes 17 bits of memory to store, the biggest 17 bit number you can store is 0x1FFFF which is 131071 which is a bit bigger than 99999. So when you want to think big numbers and math on a computer you have to think binary (or hex).
所以,当我问你要使用多少位时,这就是我的意思。看看这个数字99999.再次基数10,你会认为这是最大的数字,但对于计算机它只是那里的一部分,99999十进制是0x1869F,需要17位内存来存储,最大的17位数你可以store是0x1FFFF,这是131071,比99999大一点。所以当你想在计算机上想大数字和数学时,你必须考虑二进制(或十六进制)。
Originally you were doing multiplications, which is still part of the euler problem, but what was I was asking about was related to precision and bit storage. Here are some fundamentals, and I wont get into it but you can see why we rely on floating point units in computers.
最初你正在做乘法,这仍然是欧拉问题的一部分,但我所询问的是与精度和位存储有关。这里有一些基础知识,我不会介绍它,但你可以看到为什么我们依赖计算机中的浮点单元。
Take the largest 4 bit number 1111(binary), which is 15 decimal. Add that with the largest four bit number and you get 15+15 = 30 = 0x1E or 11110 binary. So to add two four bit numbers you need five bits to hold your answer. Computers keep a "carry" bit for this extra bit. Essentially the add/subtract integer math functions in the computer allow you to have N+1 bits. So if it is an 32 bit computer you basically have 33 bits for add/sub math.
取最大4位数1111(二进制),即十进制15。添加具有最大四位数的那个,你得到15 + 15 = 30 = 0x1E或11110二进制。因此,要添加两个四位数字,您需要五位来保持答案。计算机为这个额外的位保留一个“进位”位。本质上,计算机中的加/减整数数学函数允许您有N + 1位。因此,如果它是32位计算机,你基本上有33位用于加/子数学。
The problem is multiply and divide, which even today many processors do not support (yes many have no fpu and only do add and subtract, sometimes multiply, but divide is rare. Multiply and divide take a lot of electronics the trade off is you can do them with adds and subtracts in software). Take the worst case multiply for a four bit system 1111 * 1111 = 11100001 so it takes 8 bits to store the result of a 4 bit multiply, you will quickly find that if you had a 4 bit system MOST of the multiplies you want to do will result a number that cannot be stored in 4 bits. So when I saw you taking 64 bit integers (the unsigned long long is often 64 bits) and multiplying four times, that means you need 64*5 or a 320 bit integer to store your answer, you were trying to put that answer in a 64 big result, which quite often, depending on the compiler and computer will happily do and will truncate the upper bits leaving you with the lower 64 bits of the result which can easily look smaller than any of your operands, which is what I had thought you might have done at first.
问题是乘法和除法,即使在今天许多处理器也不支持(是的,许多处理器没有fpu,只能加减,有时会成倍增加,但除法很少。乘法和除法需要很多电子设备,你需要权衡利弊在软件中添加和减少它们。对于四位系统1111 * 1111 = 11100001采用最坏情况乘法,因此需要8位来存储4位乘法的结果,如果你有一个4位系统MOST,那么你很快就会发现将产生一个无法以4位存储的数字。因此,当我看到你采用64位整数(无符号长整数通常是64位)并乘以四次,这意味着你需要64 * 5或320位整数来存储你的答案,你试图把这个答案放在一个64大结果,这通常取决于编译器和计算机将很乐意做,并将截断高位,留下你的结果的低64位,这可能很容易看起来比你的任何操作数小,这是我所想的你可能一开始就做过。
Floating point is not much more than scientific notation but in binary, if you wanted to multiply the number 1234 and 5678 using scientific notation you would take 1.234*10^3 times 5.678*10^3 and get 7.007*10^6. You keep your precision and are able to represent a wider range of numbers. I wont get into how this works in binary. But it doesnt work for your original question.
浮点数不仅仅是科学记数法,而是二进制数,如果你想用科学计数法乘以数字1234和5678,你需要1.234 * 10 ^ 3倍5.678 * 10 ^ 3得到7.007 * 10 ^ 6。您保持精确度并能够代表更广泛的数字。我不会深入研究二进制文件的工作原理。但它对你原来的问题不起作用。
Ahh, the last thing to clarify what I was doing in my question/response. Negative integers in binary. Because of the relationships between addition and subtraction and base systems you can play some tricks. Say I wanted to subtract 1 from the number 7(decimal) using binary. Well there is no such thing as a subtract circuit, you instead add a negative number so instead of 7 - 1 it is really 7 + (-1), it makes a difference:
啊,最后要澄清我在问题/回答中做了什么。二进制中的负整数。由于加法和减法以及基本系统之间的关系,你可以玩一些技巧。假设我想使用二进制从数字7(十进制)中减去1。那么没有减法电路这样的东西,你改为添加一个负数,而不是7 - 1,它实际上是7 +( - 1),它有所不同:
0111 + ???? = 0110
0111 + ???? = 0110
What number could you add to 7 to get 6...in binary?
你可以在7中加入6来获得6 ...二进制数?
0111 + 1111 = 0110
0111 + 1111 = 0110
Negative numbers in binary are called "twos complement", long story short the answer is "invert and add 1". How do you represent minus 1 in binary? take plus one 0001 then invert it meaning make the ones zeros and the zeros ones (also known as ones complement) 1110 then add one 1111. Minus one is a special number in computers (well everywhere) as no matter how many bits you have it is represented as all ones. So when you see someone do this:
二进制中的负数称为“二进制补码”,长话短说答案是“反转并加1”。你如何在二进制中表示减1?加上一个0001然后反转它意味着使零和零(也称为补码)1110然后添加一个1111.减1是计算机中的特殊数字(无处不在),无论你有多少位表示为所有。所以当你看到有人这样做时:
unsigned char a;
unsigned char a;
a = -1;
a = -1;
The compiler first looks at that -1 and thinks ...11111(binary) then it looks at the equals sign and the other side, oh, you want a to be all ones, it sees that you have a signed integer and an unsigned but the conversion is to just move the bits over so you are saying above that you want a = 0xFF; (assuming an 8 bit unsigned char).
编译器首先查看-1并认为... 11111(二进制)然后它查看等号和另一侧,哦,你想要一个是全部的,它看到你有一个有符号整数和一个无符号但转换只是移动位,所以你在上面说你想要一个= 0xFF; (假设8位无符号字符)。
Some compilers may complain that you are trying to store a negative number in an unsigned number. Other compilers will look at that -1 and see it as a 32 bit or these days maybe 64 bit signed integer constant and then when it evaluates the equals into an 8 bit unsigned you will get a warning that you cannot store -1 in a signed or unsigned char without a typecast. But if you do this:
某些编译器可能会抱怨您正在尝试将负数存储在无符号数字中。其他编译器将查看-1并将其视为32位或这些天可能是64位有符号整数常量,然后当它将等于8位无符号时,您将收到一条警告,指出您无法在签名中存储-1或没有类型转换的unsigned char。但是如果你这样做:
a = 0; a--;
a = 0;一个 - ;
All compilers will like that. and wont complain, it just burns computing cycles at runtime instead of compile time.
所有编译器都会喜欢这样。并且不会抱怨,它只是在运行时而不是编译时烧掉计算周期。
Now somewhere a friend told me of a book that does binary math serially. For example to negate a number, usually you do the invert and ad one trick, but with pencil and paper some may tell you the other trick. Starting from the right copy the zeros up to and including the first 1 then invert after that, so minus 2
现在某个朋友告诉我一本连续二进制数学的书。例如,为了否定一个数字,通常你会做反转和广告一招,但是用铅笔和纸一些可能会告诉你另一个技巧。从正确的复制开始,将零复制到包括第一个1,然后在此之后反转,因此减去2
0010
1110
Starting from the right copy the 0 then the first one, then invert the remaining bits as you go left.
从右边开始复制0然后从第一个复制,然后在向左移动时反转剩余的位。
minus 6
0110
1010
minus 4
0100
1100
Supposedly there are tricks to do add and subtract (well duh, those are easy) but also multiply and divide. If you do them serially then you can do infinitely long math in binary with the same alu. If you were to know how to do that you could implement that in software and your original question of multiplying big constants (with the assumption of retaining all the precision) is trivial on any computer.
据说有添加和减去的技巧(好吧,那些很容易),但也是乘法和除法。如果你按顺序执行它们,那么你可以使用相同的alu进行无限长的二进制数学运算。如果你知道如何做到这一点,你可以在软件中实现它,你的原始问题是乘以大常数(假设保留所有精度)在任何计算机上都是微不足道的。
#5
1
The answer that you got, 18446744073709551496, is due to your 999...9s being truncated when assigned to a long long, plus the multiple operations overflowing. Its deterministic, but effectively just a random collection of bits.
你得到的答案,18446744073709551496,是由于你的999 ... 9s被分配到一个很长的长,加上多个操作溢出。它的确定性,但实际上只是随机的比特集合。
#6
0
unsigned int represents a system word. Today, that word will max out at either 2^32 -1 or 2^64 - 1, depending on whether your system is 32 bit or 64 bit. You're hitting the cap.
unsigned int表示系统字。今天,根据您的系统是32位还是64位,该字最大值为2 ^ 32 -1或2 ^ 64-1。你打算上限。
You have to write a bignum class or use one off the 'net.
你必须写一个bignum类或使用'net。
Why are you doing this problem anyway?
你为什么要这样做呢?
#7
0
The numbers can't fit in unsigned long long
range so either you could use GMP library or use string to represent big numbers like I did for calculating factorial of number like 50:
这些数字不适合无符号长的长距离,所以要么你可以使用GMP库,要么使用字符串代表大数字,就像我用来计算50的数字阶乘一样:
#include <cmath>
#include <iostream>
using namespace std;
int main()
{
unsigned int nd, nz;
unsigned char *ca;
unsigned int j, n=50, q, temp;
int i;
double p;
p = 0.0;
for(j = 2; j <= n; j++)
{
p += log10((double)j);
}
nd = (int)p + 1;
ca = new unsigned char[nd+1];
if (!ca)
{
cout << "Could not allocate memory!!!";
exit(0);
}
for (i = 1; (unsigned)i < nd; i++)
{
ca[i] = 0;
}
ca[0] = 1;
p = 0.0;
for (j = 2; j <= n; j++)
{
p += log10((double)j);
nz = (int)p + 1;
q = 0;
for (i = 0;(unsigned) i <= nz; i++)
{
temp = (ca[i] * j) + q;
q = (temp / 10);
ca[i] = (char)(temp % 10);
}
}
cout << "\nThe Factorial of " << n << " is: ";
for( i = nd - 1; i >= 0; i--)
{
cout << (int)ca[i];
}
// delete []ca;
return 0;
}