In most coding competitions where the output of a program is presumed to be very large,it is generally instructed to divide the output by 10000007(or in that case a prime number).What is the significance of the prime number being taken because in many cases I find that the same number is given as 100004(i.e. not a prime number)..?
A prime number is used for two reasons. One reason is that the integers modulo a prime form a mathematical field. Arithmetic in an field works in many ways like arithmetic on integers. This makes an field useful in certain contest problems where otherwise the sequences used might collapse in some cases. Certain arithmetic might produce zero, other trivial results, or simpler results than desired, because the numbers involve happen upon a factor of the modulus, causing some reduction or elimination to occur.
Another reason is to compel the programmer to deal with arithmetic on integers of a certain size. If a composite number were used, then other techniques could be used that did not resort to arithmetic with large integers.
For example, supposed we want to know what 132 is modulo 35, but we have only a very small processor that cannot handle three-digit numbers, so it cannot compute 132 = 169.
Well, 35 = 5•7, and 13 is congruent to 3 modulo 5 and 6 modulo 7. Instead of computing the square of 13, we can compute the squares of these residues, which tells us that 132 is congruent to 32 = 9 = 4 modulo 5 and is congruent to 62 = 36 = 1 modulo 7. Combining these residues requires some additional knowledge (the Extended Euclidean Algorithm). For these particular numbers, we can multiply the residue of 5 by 21 and the residue of 7 by 15 to get 4·21+1·15 = 99. Reducing that modulo 35 yields 29, which is the answer (the residue of 132 modulo 35).
If the modulus is prime, this circumvention of the arithmetic is not available. A prime modulus essentially requires the use of arithmetic on numbers up to the square of the modulus (or time-consuming workarounds), but a composite modulus would allow the use of arithmetic on smaller numbers, up to just twice the modulus.
Related
i am using 4Rungekutta to solve the DGL(Ax + Bu = x_dot) in MATLAB and C,
A is 5x5, x is 5x1, B 5x1, u 1x1, u is the output of sine function(2500 points),
the output of 4Rungekutta in MATLAB and C are all the same until 45th iteration, but at 45th(in 2500 iterations) iteration of 4Rungekutta the output of A*x at 2th Step of 4Rungekutta are different , hier are the Matrix.
i have printed them with 30 decimals
A and x are the same in MATLAB and C
A = [0, 0.100000000000000005551115123126,0,0,0;
-1705.367199390822406712686643004417 -13.764624913971095665488064696547 245874.405372532171895727515220642090 0.000000000000000000000000000000 902078.458362009725533425807952880859;
0, 0, 0, 0.100000000000000005551115123126, 0;
2.811622989796986438193471258273, 0, -572.221510883482778808684088289738, -0.048911651728553134921284595293 ,0;
0, 0, -0.100000000000000005551115123126 0, 0]
x = [0.071662614269441649028635765717 ;
45.870073568955461951190955005586;
0.000002088948888569741376840423;
0.002299524406171214990085571728;
0.000098982102875767145086331744]
but the results of A*x are not the same,the second element in MATLAB is-663.792187417201375865261070430279,in C is
-663.792187417201489552098792046309
MATLAB
A*x = [ 4.587007356895546728026147320634
-663.792187417201375865261070430279
0.000229952440617121520692600622
0.200180438762844026268084007825
-0.000000208894888856974158859866];
C
A*x = [4.587007356895546728026147320634
-663.792187417201489552098792046309
0.000229952440617121520692600622
0.200180438762844026268084007825
-0.000000208894888856974158859866];
though the difference is small, but i need this result to do the finite difference, at that point the result would be more obvious
does anyone know why?
How many digits do you consider you need? You have the same first 16 digits of each number equal, which is the aproximate amount of data a double normally can represent internally and store. You cannot get more, even if you force your printing routines to print more digits, they will print rubbish. What happens is that you have said to get say, 120 digits to your printing routines... and they will print those, normally multiplying the remainder (whatever it can be) As numbers are represented in base 2, you normally don't get zeros once passed the internal precission of the number... and the printing implementations don't have to agree on the digits printed once you don't have more bits represented in your number.
Suppose for a moment you have a hand calculator that only has 10 digits of precision. And you are given numbers of 120 digits. You begin to calculate and only get results with 10 digits... but you have been requested to print a report with 120 digit results. Well.... as the overal calculation cannot be done with more than 10 digits what can you do? you are using a calculator unable to give you the requested number of digits... and more, the number of base 10 digits in a 52bit significand is not a whole number of digits (there are 15.65355977452702215111442252567364 decimal digits in a 52bit significand). What can you do, you can fill with zeros (incorrect, most probably) you can fill those places with rubish (that will never affect the final 10 digits result) or you can go to Radio Shack and buy a 120 digit calculator. Floating point printing routines use a counter to specify how many times to go into a loop and get another digit, they normally stop when the counter reaches it's limit, but don't do any extra effort to know if you have got crazy and specified a large amount of digits... if you ask for 600 digits, you just get 600 loop iterations, but digits will be fake.
You should expect a difference of one part in 2^52 in a double number, as those are the number of binary digits used for the significand (this is aprox 2,220446049250313080847263336181641e-16, so you have to multiply this number by the one you have output to see how large the rounding error is, aproximately) if you multiply your number 663.792187417201375865261070430279 by that, you get 1.473914740073748177152126604805902e-13, which is an estimate of where in the number is the last valid digit of it. Probably the error estimate will be far larger due to the large number o multiplications and sums required to make a cell calculation. Anyway, a resolution of 1.0e-13 is very good (subatomic difference, should the values be lengths and units in meters).
EDIT
as an example, just consider the following program:
#include <stdio.h>
int main()
{
printf("%.156f\n", 0.1);
}
if you run it you'll get:
0.100000000000000005551115123125782702118158340454101562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
which indeed is the most (exact) aproximation to the internal representation of the number 0.1 that the machine can represent in base 2 floating point (0.1 happens to be a periodic number, when represented in base 2) Its representation is:
0.0001100110011(0011)*
so it cannot be represented exactly with 52 bits repeating the pattern 1100 indefinitely. At some point you have to cut, and the printf routine continues adding zeros to the right until it gets to the representation above (all the finite digit numbers in base 2 are representable as a finite number of digits in base 10, but the converse is not true, (because all the factors of 2 are in 10, but not all the factors of 10 are in 2).
If you divide the difference from 0.1 and 0.1000000000000000055511151231257827021181583404541015625 between 0.1 you'll get 5.55111512312578270211815834045414e-17 which is approximately 1/2^54 or one quarter approximately (roughly one fifth) of the limit 1/2^52 I showed to you above. It is the closest number representable with 52 bits to the number 0.1
I try to write a factorial function to compute a large number(factorial(105)),its result have 168 digit, so use long double, but it seems to be a error, can't it use like this?
#include <stdio.h>
long double factorial(long double n,long double base = 1){
if (n <= 1){
return 1*base;
}else{
return factorial(n-1,n * base);
}
}
int main(){
printf("%.0Lf\n",factorial(25)); // this result is correct
printf("%.0Lf\n",factorial(26));
//correct result is 403291461126605635584000000,but it return 403291461126605635592388608
return 0;
}
Back of the envelope calculation: 25! is slightly more than 1025; three orders of magnitude is roughly 10 bits, so you would need roughly 83 bits of mantissa even just to represent precisely the result.
Given that a long double, on platforms that support it, is generally 80 bits for the whole value (not just the mantissa!), apparently there's no way you have enough mantissa to perform that calculations of that order of magnitude with integer precision.
However: factorial here is a bit magic, as many of the factors contain powers of two, which just add binary zeroes to the right, which do not require mantissa (they end up in the exponent). In particular:
25! = 2 4 2 8 2 4 2 16 2 4 2 8 = 2²² · m
3 5 3 7 9 5 11 3 13 7 15 17 9 19 5 21 11 23 3 25
(m being the product of all non-2 factors, namely m = 310 · 56 · 73 · 112 · 13 · 17 · 19 · 23, so effectively the data we have to store in the mantissa)
Hence, our initial estimate exceeds the actual requirements by 22 bits.
It turns out that
log2(f) = 10·log23 + 6·log25 + 3·log27 + 2·log211 + log213 + log217 + log219 + log223 = 61.68
which is indeed just below the size of the mantissa of 80 bit long double (64 bit). But when you multiply it by 26 (so, excluding the factor 2, which ends up in the exponent, by 13), you are adding log2(13) = 3.7 bits. 61.7+3.7 is 65.4, so from 26! onwards you no longer have the precision to perform your calculation exactly.
Firstly, nobody knows what long double can or cannot represent. Specific properties of the format depend on the implementation.
Secondly, X86 extended precision floating-point format has 64-bit significand with explicit leading 1, which means that it can represent contiguous integers in ±264 range. Beyond that range representable integers are non-contiguous (i.e. they begin to "skip" with wider and wider gaps). Your factorials fall far outside that range, meaning that it is perfectly expected that they won't be represented precisely.
Since 105! is a huge number that does not fit in a single word (or two of them), you want arbitrary precision arithmetic, also known as bignums. Use the Stirling's approximation to get an idea of how big 105! is and read the wikipage on factorials.
Standard C (read n1570 to check) don't have bignums natively, but you'll find many libraries for that.
I recommend GMPlib. BTW, some of its code is hand-written assembly for performance reason (when coding bignum addition, you want to take advantage of add with carry machine instructions).
I recommend to avoid writing your own bignum operations. The existing libraries use very clever algorithms (and you'll need to make some PhD work to get something better). If you try coding your own bignum library, it probably will be much worse than competitors (unless you spend years of work).
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
No data type can store such large number. Using array
int a[pow(10,pow(10,18))] again won't do the job because pow() returns double and double can't store 10^(10^18).
Anyone having any idea?
I'm trying to solve the following problem:
Consider an integer with N
digits (in decimal notation, without leading zeroes) D1,D2,D3,…,DN. Here, D1 is the most significant digit and DN the least significant. The weight of this integer is defined as:
∑ i=2 -> N (Di−Di−1).
You are given integers N and W. Find the number of positive integers with N digits (without leading zeroes) and weight equal to W. Compute this number modulo 109+7.
Input:
The first line of the input contains a single integer T denoting the number of test cases. The description of T test cases follows.
The first and only line of each test case contains two space-separated integers N and W denoting the number of digits and the required weight.
Output:
For each test case, print a single line containing one integer — the number of N-digit positive integers with weight W, modulo 109+7.
Constraints:
1≤T≤105
2≤N≤1018
|W|≤300
You don't need to store a number with 10^18 digits. Look at the definition of the weight:
∑ i=2 -> N (Di−Di−1)
Each element in the sum is the difference of two consecutive digits.
Let's take for example a 4 digit number whose digits are D1, D2, D3, D4. Then the sum is:
(D2 - D1) + (D3 - D2) + (D4 - D3)
Reording the operands:
D4 - D3 + D3 - D2 + D2 - D1
You'll see that all but the first and last digits cancel out! So the whole sum is D4 - D1. In fact, for any number of digits N, the sum is:
DN - D1
So only the first and the last digits are relevant. You should be able to figure out the rest from there.
There are libraries for handling these sorts of problems, like The GNU
Multiple Precision
Arithmetic Library:
What is GMP?
GMP is a free library for arbitrary precision arithmetic, operating on signed integers, rational numbers, and floating-point numbers. There is no practical limit to the precision except the ones implied by the available memory in the machine GMP runs on. GMP has a rich set of functions, and the functions have a regular interface.
The main target applications for GMP are cryptography applications and research, Internet security applications, algebra systems, computational algebra research, etc.
But 10^18 would take a huge (and effectively impossible) amount of memory (if my math is correct: 2.881 EiB).
The referenced problem takes input from 2 ≤ N ≤ 10^18. That isn't 10^18 digits (or 10^10^18 which is absurdly enormous) but 18 digits or 2 to 1,000,000,000,000,000,000. This will fit inside a 64 bit integer, signed or unsigned.
Use int64_t from stdint.h.
10^18 is pushing the limits of 64 bit integers, probably why they chose it. Anything larger should use an arbitrary precision math library such as GMP.
...but there are limits. Simply storing such a number would take about 1 million gigabytes. So while the problem is about solving for numbers with 10^18 digits, I strongly suspect you're not supposed to solve it by actually storing those numbers. There's some mathematical technique you're supposed to apply.
I wrote this code that simply sums a list of n numbers, to practice with floating point arithmetic, and I don't understand this:
I am working with float, this means I have 7 digits of precision, therefore, if I do the operation 10002*10002=100040004, the result in data type float will be 100040000.000000, since I lost any digit beyond the 7th (the program still knows the exponent, as seen here).
If the input in this program is
3
10000
10001
10002
You will see that, however, when this program computes 30003*30003=900180009 we have 30003*30003=900180032.000000
I understand this 32 appears becasue I am working with float, and my goal is not to make the program more precise but understand why this is happening. Why is it 900180032.000000 and not 900180000.000000? Why does this decimal noise (32) appear in 30003*30003 and not in 10002*10002 even when the magnitude of the numbers are the same? Thank you for your time.
#include <stdio.h>
#include <math.h>
#define MAX_SIZE 200
int main()
{
int numbers[MAX_SIZE];
int i, N;
float sum=0;
float sumb=0;
float sumc=0;
printf("introduce n" );
scanf("%d", &N);
printf("write %d numbers:\n", N);
for(i=0; i<N; i++)
{
scanf("%d", &numbers[i]);
}
int r=0;
while (r<N){
sum=sum+numbers[r];
sumb=sumb+(numbers[r]*numbers[r]);
printf("sum is %f\n",sum);
printf("sumb is %f\n",sumb);
r++;
}
sumc=(sum*sum);
printf("sumc is %f\n",sumc);
}
As explained below, the computed result of multiplying 10,002 by 10,002 must be a multiple of eight, and the computed result of multiplying 30,003 by 30,003 must be a multiple of 64, due to the magnitudes of the numbers and the number of bits available for representing them. Although your question asks about “decimal noise,” there are no decimal digits involved here. The results are entirely due to rounding to multiples of powers of two. (Your C implementation appears to use the common IEEE 754 format for binary floating-point.)
When you multiply 10,002 by 10,002, the computed result must be a multiple of eight. I will explain why below. The mathematical result is 100,040,004. The nearest multiples of eight are 100,040,000 and 100,040,008. They are equally far from the exact result, and the rule used to break ties chooses the even multiple (100,040,000 is eight times 12,505,000, an even number, while 100,040,008 is eight times 12,505,001, an odd number).
Many C implementations use IEEE 754 32-bit basic binary floating-point for float. In this format, a number is represented as an integer M multiplied by a power of two 2e. The integer M must be less than 224 in magnitude. The exponent e may be from −149 to 104. These limits come from the numbers of bits used to represent the integer and the exponent.
So all float values in this format have the value M • 2e for some M and some e. There are no decimal digits in the format, just an integer multiplied by a power of two.
Consider the number 100,040,004. The biggest M we can use is 16,777,215 (224−1). That is not big enough that we can write 100,040,004 as M • 20. So we must increase the exponent. Even with 22, the biggest we can get is 16,777,215 • 22 = 67,108,860. So we must use 23. And that is why the computed result must be a multiple of eight, in this case.
So, to produce a result for 10,002•10,002 in float, the computer uses 12,505,000 • 23, which is 100,040,000.
In 30,003•30,003, the result must be a multiple of 64. The exact result is 900,180,009. 25 is not enough because 16,777,215•25 is 536,870,880. So we need 26, which is 64. The two nearest multiples of 64 are 900,179,968 and 900,180,032. In this case, the latter is closer (23 away versus 41 away), so it is chosen.
(While I have described the format as an integer times a power of two, it can also be described as a binary numeral with one binary digit before the radix point and 23 binary digits after it, with the exponent range adjusted to compensate. These are mathematically equivalent. The IEEE 754 standard uses the latter description. Textbooks may use the former description because it makes analyzing some of the numerical properties easier.)
Floating point arithmetic is done in binary, not in decimal.
Floats actually have 24 binary bits of precision, 1 of which is a sign bit and 23 of which are called significand bits. This converts to approximately 7 decimal digits of precision.
The number you're looking at, 900180032, is already 9 digits long and so it makes sense that the last two digits (the 32) might be wrong. The rounding like the arithmetic is done in binary, the reason for the difference in rounding can only be seen if you break things down into binary.
900180032 = 110101101001111010100001000000
900180000 = 110101101001111010100000100000
If you count from the first 1 to the last 1 in each of those numbers (the part I put in bold), that is how many significand bits it takes to store the number. 900180032 takes only 23 significand bits to store while 900180000 takes 24 significand bits which makes 900180000 an impossible number to store as floats only have 23 significand bits. 900180032 is the closest number to the correct answer, 900180009, that a float can store.
In the other example
100040000 = 101111101100111110101000000
100040004 = 101111101100111110101000100
The correct answer, 100040004 has 25 significand bits, too much for floats. The nearest number that has 23 or less significand bits is 10004000 which only has 21 significant bits.
For more on floating point arithmetic works, try here http://steve.hollasch.net/cgindex/coding/ieeefloat.html
Say I have 16 64-bit unsigned integers. I have been careful to feed the carry as appropriate between them when performing operations. Could I feed them into a method to convert all of them into a single string of decimal digits, as though it was one 1024-bit binary number? In other words, is it possible to make a method that will work for an arbitrary number of integers that represent one larger integer?
I imagine that it would be more difficult for signed integers, as there is the most significant bit to deal with. I suppose it would be that the most significant integer would be the signed integer, and the rest would be unsigned, to represent the remaining 'parts' of the number.
(This is semi-related to another question.)
You could use the double dabble algorithm, which circumvents the need for multi-precision multiplication and division. In fact, the Wikipedia page contains a C implementation for this algorithm.
This is a bit unclear.
Of course, a function such as
void print_1024bit(uint64_t digits[]);
could be written to do this. But if you mean if any of the standard library's printf()-family of functions can do this, then I think the answer is no.
As you probably saw in the other question, the core of converting a binary number into a different base b is made of two operations:
Modulo b, to figure out the current least significant digit
Division by b, to remove that digit once it's been generated
When applied until the number is 0, this generates all the digits in reverse order.
So, you need to implement "modulo 10" and "divide by 10" for your 1024-bit number.
For instance, consider the number decimal 4711, which we want to convert to octal just for this example:
4711 % 8 is 7, so the right-most digit is 7
4711 / 8 is 588
588 % 8 is 4, the next digit is 4
588 / 8 is 73
73 % 8 is 1
73 / 8 is 9
9 % 8 is 1
8 / 8 is 1
1 % 8 is 1
1 / 8 is 0, we're done.
So, reading the bold digits from the bottom and up towards the right-most digits, we conclude that 471110 = 111478. You can use a calculator to verify this, or just trust me. :)
It's possible, of course, but not terribly straight-forward.
Rather than reinventing the wheel, how about reusing a library?
The GNU Multi Precision Arithmetic Library is one such possibility. I've not needed such things myself, but it seems to fit your bill.