simple GMP/MPIR questions - gmp

I'm trying out GMP/MPIR with VS 2010, I don't understand why the output is 0.999999999999999999909e101 for input 10 10.
I'd expect all the digits to show because i put 1000 for n_digits in mpf_out_str call, using 0 same result. And why the 9's, and 909e101?
Also how would you input huge numbers, gmp_scanf doesn't seem to handle 100's of digits.
#include <mpirxx.h>
main()
{
mpf_t tt, t2;
mpf_init(tt);
mpf_init(t2);
gmp_scanf("%Fe\n", tt);
gmp_scanf("%Fe\n", t2);
for (int i = 0; i < 100; i++)
mpf_mul(tt, tt, t2);
mpf_out_str(stdout, 10, 1000, tt);
mpf_clear(tt);
mpf_clear(t2);
getc(stdin);
}

You need to specify the precision of an mpf_t. See mpf_init2() and mpf_set_default_prec().

Related

Something weird in for loop speed

here is a part of my program code:
int test;
for(uint i = 0; i < 1700; i++) {
test++;
}
the whole program takes 0.5 seconds to finish, but when I change it to:
int test[1];
for(uint i = 0; i < 1700; i++) {
test[0]++;
}
it will takes 3.5 seconds! and when I change the int to double, it will gets very worse:
double test;
for(uint i = 0; i < 1700; i++) {
test++;
}
it will takes about 18 seconds to finish !!!
I have to increase an int array element and a double variable in my real for loop, and it will takes about 30 seconds!
What's happening here?! Why should it takes that much time for just an increment?!
I know a floating point data type like double has different structure from a fixed point data type like int, but is it the only cause for such a big different time? and what about the second example which is also an int array element?!
Thanks
You have answered your question yourself.
float (double) operations are different from integer ones. Even if you just add 1.0f.
Your second example takes longer than the first one just because you added some pointer refernces. An array in C is -bottom down- not much different from a pointer to the first element. Accessing any element, even the first one, would cause the machine code to load the starting address of the array multiply the index (0 in this case) with the length of each member (4 or whatever bytes int has) and add that (0) to the pointer. Then it has to dereference the pointer, meaning to acutally load the value at that very address. Add one and write back the result.
A smart modern compiler should optimize this a bit. When you want to avoid this optimization, then modify the code a bit and don`t use a constant for the index.
I never tried that with a modern objective-c compiler. But I guess that this code would take much loger than 3.5s to run:
int test[2];
int index = 0;
for(uint i = 0; i < 1700; i++) {
test[index]++;
}
If that does not make much of a change then try this:
-(void)foo:(int)index {
int test[2];
for(uint i = 0; i < 1700; i++) {
test[index]++;
}
}
and then call foo:0;
Give it a try and let us know :)

Multiplying array doubles

This code returns error 'Invalid operands to binary expressions double and double'
double staticDouble[3] = {1,2,3};
double dynamicDouble[3] = {a, b, c};
double resultTest = static * dynamic;
NSLog(#"%f",resultTest);
What I want this to do is to multiply 1 with a, 2 with b and 3 with c. abc are double values fetched from a textfield. How should I do this properly?
The problem is that static and dynamic are arrays, and there's no * operator for arrays; only for "arithmetic" types. (Also, having an array named static is a problem, but I'm going to ignore that for the purposes of answering the question you actually asked).
Two options: compute the products one at a time:
double resultTest[3];
for (int i=0; i<3; ++i) resultTest[i] = static[i] * dynamic[i];
or call a library function that operates on vectors; for instance on iOS or OS X, you can do (you'll also need to link against the Accelerate framework):
#include <Accelerate/Accelerate.h>
...
double resultTest[3];
vDSP_vmul(static, 1, dynamic, 1, resultTest, 1, 3);
(This is slight overkill for arrays of size three; if you're going to be working exclusively with such small arrays, you may want to define your own functions or use a library that targets small fix-sized vector operations, like GLKit).
You'll run into the same problem printing the results; there's no format string to print the contents of an array, so you need to print the elements one at a time:
for (int i=0; i<3; ++i) NSLog(#"%f ", resultTest[i]);

get an integer -unit digit in a simple way

i am not sure about my english, but i need to get the unit digit of an integer.
WITHOUT complex algorithm but with some API or another trick.
for example :
int a= 53;
int b=76;
this i add because i almost always dont "meet the quality standards" to post! its drive me crazy! please , fix it ! it took me 10 shoots to post this,and other issue also.
i need to get a=3 and b=6 in a simple smart way.
same about the other digit.
thanks a lot .
here is how to split the number into parts
int unitDigit = a % 10; //is 3
int tens= (a - unitDigit)/10; //is 53-3=50 /10 =5
You're looking for % operator.
a=a%10;//divides 'a' by 10, assigns remainder to 'a'
WARNING
here is how to divine the number into parts
int unitDigit = a % 10; //is 3
int tens= (a - unitDigit)/10; //is 53-3=50 /10 =5
this answer is totally incorrect. It may work only in a number of cases. For example try to get the first digit of 503 via this way
It seems the simplest answer (but not very good in performance):
int a = ...;
int digit = [[[NSString stringWithFormat:#"%d", a] substringToIndex:1] intValue]; //or use substringWithRange to get ANY digit
Modulo operator will help you (as units digit is a reminder when number is divided by 10):
int unitDigit = a % 10;
The following code "gets" the digits of a given number and counts how many of them divide the number exactly.
int findDigits(long long N){
int count = 0;
long long newN = N;
while(newN) // kinda like a right shift
{
int div = newN % 10;
if (div != 0)
if (N % div == 0) count++;
newN = newN / 10;
}
return count;
}

Which are faster squares or roots?

for (int i = 2; i * i <= n; i++)
for (int i = 2; i <= SQRT(n); i++)
just wondering which is faster I looked at some primitive algorithms for getting roots and it would seem to me that squaring the number would be faster but I don't know for sure. These loops are for determining a numbers "primeness".
Shouldn't the comaprison be between
int sqrt = SQRT(n);
for (int i = 2; i <= sqrt; i++)
and
for (int i = 2; i * i <= n; i++)
The answer will depend on how many loop iterations you do. The sqrt method does less work per iteration, but it has a higher start-up cost. Mind you, this reeks of premature optimisation.
Compiler may 'cache' result of SQRT (n), but i * i it should compute on each step.
Square root will take longer, unless it's implemented in hardware, lookup, or a special machine code version. Newton iteration is the algorithm of choice; it converges quadratically.
Best to benchmark for yourself. I'd recommend moving the call to square root outside the loop so you only do it once rather than every time you check the exit condition.
Why not skip both of them and use some clever maths? The Following code avoid both of them using the Property that Sum of the First n odd numbers is always a perfect square.
A shameless plug for my old blogpost (from my dead blog)
int isPrime(int n)
{
int squares = 1;
int odd = 3;
if( ((n & 1) == 0) || (n < 9)) return (n == 2) || ((n > 1) && (n & 1));
else
{
for( ;squares <= n; odd += 2)
{
if( n % odd == 0)
return 0;
squares+=odd;
}
return 1;
}
}
The square will be faster.
But the square will overflow if n is larger than the square root of the largest int, and then the comparison will go wrong. The square root function could (and you would expect to) be implemented in such a way that is can be calculated on arguments all the way up to the largest representable int. That means it won't go wrong in that way.
In Java, the largest int is 2^31 - 1, which means its square root is just under 46341. If you want to look for primes larger than that, the squaring would stop you.

Objective c, Scanf() string taking in the same value twice

Hi all I am having a strange issue, when i use scanf to input data it repeats strings and saves them as one i am not sure why.
Please Help
/* Assment Label loop - Loops through the assment labels and inputs the percentage and the name for it. */
i = 0;
j = 0;
while (i < totalGradedItems)
{
scanf("%s%d", assLabel[i], &assPercent[i]);
i++;
}
/* Print Statement */
i = 0;
while (i < totalGradedItems)
{
printf("%s", assLabel[i]);
i++;
}
Input Data
Prog1 20
Quiz 20
Prog2 20
Mdtm 15
Final 25
Output Via Console
Prog1QuizQuizProg2MdtmMdtmFinal
Final diagnosis
You don't show your declarations...but you must be allocating just 5 characters for the strings:
When I adjust the enum MAX_ASSESSMENTLEN from 10 to 5 (see the code below) I get the output:
Prog1Quiz 20
Quiz 20
Prog2Mdtm 20
Mdtm 15
Final 25
You did not allow for the terminal null. And you didn't show us what was causing the bug! And the fact that you omitted newlines from the printout obscured the problem.
What's happening is that 'Prog1' is occupying all 5 bytes of the string you read in, and is writing a null at the 6th byte; then Quiz is being read in, starting at the sixth byte.
When printf() goes to read the string for 'Prog1', it stops at the first null, which is the one after the 'z' of 'Quiz', producing the output shown. Repeat for 'Prog2' and 'Mtdm'. If there was an entry after 'Final', it too would suffer. You are lucky that there are enough zero bytes around to prevent any monstrous overruns.
This is a basic buffer overflow (indeed, since the array is on the stack, it is a basic Stack Overflow); you are trying to squeeze 6 characters (Prog1 plus '\0') into a 5 byte space, and it simply does not work well.
Preliminary diagnosis
First, print newlines after your data.
Second, check that scanf() is not returning errors - it probably isn't, but neither you nor we can tell for sure.
Third, are you sure that the data file contains what you say? Plausibly, it contains a pair of 'Quiz' and a pair of 'Mtdm' lines.
Your variable j is unused, incidentally.
You would probably be better off having the input loop run until you are either out of space in the receiving arrays or you get a read failure. However, the code worked for me when dressed up slightly:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char assLabel[10][10];
int assPercent[10];
int i = 0;
int totalGradedItems = 5;
while (i < totalGradedItems)
{
if (scanf("%9s%d", assLabel[i], &assPercent[i]) != 2)
{
fprintf(stderr, "Error reading\n");
exit(1);
}
i++;
}
/* Print Statement */
i = 0;
while (i < totalGradedItems)
{
printf("%-9s %3d\n", assLabel[i], assPercent[i]);
i++;
}
return 0;
}
For the quoted input data, the output results are:
Prog1 20
Quiz 20
Prog2 20
Mdtm 15
Final 25
I prefer this version, though:
#include <stdio.h>
enum { MAX_GRADES = 10 };
enum { MAX_ASSESSMENTLEN = 10 };
int main(void)
{
char assLabel[MAX_GRADES][MAX_ASSESSMENTLEN];
int assPercent[MAX_GRADES];
int i = 0;
int totalGradedItems;
for (i = 0; i < MAX_GRADES; i++)
{
if (scanf("%9s%d", assLabel[i], &assPercent[i]) != 2)
break;
}
totalGradedItems = i;
for (i = 0; i < totalGradedItems; i++)
printf("%-9s %3d\n", assLabel[i], assPercent[i]);
return 0;
}
Of course, if I'd set up the scanf() format string 'properly' (meaning safely) so as to limit the length of the assessment names to fit into the space allocated, then the loop would stop reading on the second attempt:
...
char format[10];
...
snprintf(format, sizeof(format), "%%%ds%%d", MAX_ASSESSMENTLEN-1);
...
if (scanf(format, assLabel[i], &assPercent[i]) != 2)
With MAX_ASSESSMENTLEN at 5, the snprintf() generates the format string "%4s%d". The code compiled reads:
Prog 1
and stops. The '1' comes from the 5th character of 'Prog1'; the next assessment name is '20', and then the conversion of 'Quiz' into a number fails, causing the input loop to stop (because only one of two expected items was converted).
Despite the nuisance value, if you want to make your scanf() strings adjust to the size of the data variables it is reading into, you have to do something akin to what I did here - format the string using the correct size values.
i guess, you need to put a
scanf("%s%d", assLabel[i], &assPercent[i]);
space between %s and %d here.
And it is not saving as one. You need to put newline or atlease a space after %s on print to see difference.
add:
when i tried
#include <stdio.h>
int main (int argc, const char * argv[])
{
char a[1][2];
for(int i =0;i<3;i++)
scanf("%s",a[i]);
for(int i =0;i<3;i++)
printf("%s",a[i]);
return 0;
}
with inputs
123456
qwerty
sdfgh
output is:
12qwsdfghqwsdfghsdfgh
that proves that, the size of string array need to be bigger then decleared there.