10k by 10k matrix malloc curiousity in c [duplicate] - c

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
how to sum a large number of float number?
I have a matrix 'x' that is 10,000 elements by 10,000 elements.
In the first case I declare the matrix like:
int n = 10000;
unsigned int size_M = n*n;
unsigned int mem_size_M = sizeof(int)*size_M;
int* x = (int*)malloc(mem_size_M);
Step (1) The matrix is initialized:
for(i=0;i<n;i++)
for(j=0;j<n;j++)
x[i*n+j] = 1;
Step (2) Sum the elements of the matrix and print the total:
for(i=0i<n;i++)
for(j=0j<n;j++)
sum +=x[i*n+j];
printf("sum: %d \n", sum);
As I would expect the above code prints 'sum: 100000000 '.
However if I declare the matrix like:
int n = 10000;
float size_M = n * n;
float mem_size_M = sizeof(float) * size_M;
float* x = (float*)malloc(mem_size_M);
And again perform the steps 1 and 2 the correct answer is not printed out, but '16777216' instead. Why is this?
ANSWER: To get the appropriate answer do a type conversion...
sum +=(int)x[i*n+j];

This happens because of the precision limitations of the float type. You can't just add 1.0 to float with value > 16777216 (2^24), but you can add 2.0, or 0.1:
#include <stdio.h>
int main(void)
{
float f = 16777220;
printf("f = %f\n", f + 1);
printf("f = %f\n", f + 2);
printf("f = %f\n", f + 0.1);
return 0;
}
The IEEE-754 standard floating-point numbers have have 4 bytes, consisting of a sign bit, an 8-bit excess-127 binary exponent, and a 23-bit mantissa. It's a bit complicated to explain precisely why it happens, but I can say that this is a extreme case when operation error reaches its maximum.

Related

Integer variables in C [duplicate]

This question already has answers here:
Why dividing two integers doesn't get a float? [duplicate]
(7 answers)
Why does division result in zero instead of a decimal?
(5 answers)
Dividing 1/n always returns 0.0 [duplicate]
(3 answers)
Closed 2 years ago.
I am trying to write a code that finds pi accurately. When I run my code I get an output of 1.000000 every time because n always equals 0 in the equation to find add and minus after the first equation but when I print it, n is increasing as it should. I don't get any error messages because there are no visible problems with the code that I have. This is a conversion from the same code I wrote in python and I don't know if that is meaning I have forgotten something.
#include <stdio.h>
int main()
{
int n = 1, iterations, times;
long double pi = 0.0, add, minus;
printf("Number of iterations: ");
scanf("%d", &iterations);
for (times = 1; times <= iterations; ++times)
{
add = 1 / n;
printf("%Lf \n", add);
pi = pi + add;
n = n + 2;
minus = 1 / n;
printf("%Lf \n", minus);
pi = pi - minus;
n = n + 2;
printf("%d \n", n);
printf("%Lf \n", pi);
}
pi *= 4;
printf("Pi = %Lf \n", pi);
return 0;
}
Works a treat if you define n as a double.
When n is defined as an integer 'minus = 1 / n;' will always be 0, except when n = 1;

Why Is This Factorial Algorithm Not Accurate

Sorry I feel stupid asking this and am prepared to lose half of my points asking this but why does this algorithm not work? It works up to a point. After the number 13 the factorials are a little off. For instance the numbers do not entirely match in the hundreds thousands place and onward.
#include <stdio.h>
float factorial(unsigned int i) {
if (i <= 1) {
return 1;
}
return i * factorial(i - 1);
}
int main() {
int i = 13;
printf("Factorial of %d is %f\n", i, factorial(i));
return 0;
}
Here's the output:
Factorial of 13 is 6227020800.000000
Here is an example of inaccurate output:
Factorial of 14 is 87178289152.000000
The output for the number 14 should actually be this (from mathisfun.com)
14 87,178,291,200
I changed the return type to float to obtain more accurate output but I obtained this code for the most part from here: https://www.tutorialspoint.com/cprogramming/c_recursion.htm
EDIT: If I change to the return type to double the output is accurate up to 21.I am using the %Lf string formatter for the output in the printf function.
Simple. float cannot accurately store integers above 16777216 without loss of precision.
int is better than float. But try long long so you can properly store 19 digits.
OP is encountering the precision limits of float. For typical float, whole number values above 16777216.0f are not all exactly representable. Some factorial results above this point are exactly representable.
Let us try this with different types.
At 11!, the float results exceeds 16777216.0f and is exactly correct.
At 14!, the float result is imprecise because of limited precision.
At 23!, the double result is imprecise because of limited precision.
At 22!, the answer exceeds my uintmax_t range. (64-bit)
At 35!, the answer exceeds my float range.
At 171!, the answer exceeds my double range.
A string representation is accurate endlessly until it reaches buffer limitations.
#include <stdint.h>
#include <string.h>
#include <stdio.h>
uintmax_t factorial_uintmax(unsigned int i) {
if (i <= 1) {
return 1;
}
return i * factorial_uintmax(i - 1);
}
float factorial_float(unsigned int i) {
if (i <= 1) {
return 1;
}
return i * factorial_float(i - 1);
}
double factorial_double(unsigned int i) {
if (i <= 1) {
return 1;
}
return i * factorial_double(i - 1);
}
char * string_mult(char *y, unsigned base, unsigned x) {
size_t len = strlen(y);
unsigned acc = 0;
size_t i = len;
while (i > 0) {
i--;
acc += (y[i] - '0') * x;
y[i] = acc % base + '0';
acc /= base;
}
while (acc) {
memmove(&y[1], &y[0], ++len);
y[0] = acc % base + '0';
acc /= base;
}
return y;
}
char *factorial_string(char *dest, unsigned int i) {
strcpy(dest, "1");
for (unsigned m = 2; m <= i; m++) {
string_mult(dest, 10, m);
}
return dest;
}
void factorial_test(unsigned int i) {
uintmax_t u = factorial_uintmax(i);
float f = factorial_float(i);
double d = factorial_double(i);
char s[2000];
factorial_string(s, i);
printf("factorial of %3d is uintmax_t: %ju\n", i, u);
printf(" float: %.0f %s\n", f, "*" + (1.0 * f == u));
printf(" double: %.0f %s\n", d, "*" + (d == u));
printf(" string: %s\n", s);
}
int main(void) {
for (unsigned i = 11; i < 172; i++)
factorial_test(i);
return 0;
}
Output
factorial of 11 is uintmax_t: 39916800
float: 39916800
double: 39916800
string: 39916800
factorial of 12 is uintmax_t: 479001600
float: 479001600
double: 479001600
string: 479001600
factorial of 13 is uintmax_t: 6227020800
float: 6227020800
double: 6227020800
string: 6227020800
factorial of 14 is uintmax_t: 87178291200
float: 87178289152 *
double: 87178291200
string: 87178291200
factorial of 20 is uintmax_t: 2432902008176640000
float: 2432902023163674624 *
double: 2432902008176640000
string: 2432902008176640000
factorial of 21 is uintmax_t: 14197454024290336768
float: 51090940837169725440 *
double: 51090942171709440000 *
string: 51090942171709440000
factorial of 22 is uintmax_t: 17196083355034583040
float: 1124000724806013026304 *
double: 1124000727777607680000 *
string: 1124000727777607680000
factorial of 23 is uintmax_t: 8128291617894825984
float: 25852017444594485559296 *
double: 25852016738884978212864 *
string: 25852016738884976640000
factorial of 34 is uintmax_t: 4926277576697053184
float: 295232822996533287161359432338880069632 *
double: 295232799039604119555149671006000381952 *
string: 295232799039604140847618609643520000000
factorial of 35 is uintmax_t: 6399018521010896896
float: inf *
double: 10333147966386144222209170348167175077888 *
string: 10333147966386144929666651337523200000000
factorial of 170 is uintmax_t: 0
float: inf *
double: 72574156153079940453996357155895914678961840000000... *
string: 72574156153079989673967282111292631147169916812964...
factorial of 171 is uintmax_t: 0
float: inf *
double: inf *
string: 12410180702176678234248405241031039926166055775016...
Someone posted a similar question a while back. The consensus was if you're writing it for work use a big number library (like GMP) and if it's a programming exercise write up a solution using a character array.
For example:
/* fact50.c
calculate a table of factorials from 0! to 50! by keeping a running sum of character digits
*/
#include <stdio.h>
#include <string.h>
int main (void)
{
printf ("\n Table of Factorials\n\n");
// length of arrays = 65 character digits
char str[] =
"00000000000000000000000000000000000000000000000000000000000000000";
char sum[] =
"00000000000000000000000000000000000000000000000000000000000000001";
const int len = strlen (str);
int index;
for ( int i = 0; i <= 50; ++i ) {
memcpy (str, sum, len);
for ( int j = 1; j <= i - 1; ++j ) {
index = len - 1;
int carry = 0;
do {
int digit = (sum[index] - '0') + (str[index] - '0') + carry;
carry = 0;
if ( digit > 9 ) {
carry = 1;
digit %= 10;
}
sum[index] = digit + '0';
--index;
}
while ( index >= 0 );
}
printf ("%2i! = ", i);
for ( index = 0; sum[index] == '0'; ++index )
printf ("%c", '.');
for ( ; index < len; ++index )
printf ("%c", sum[index]);
printf ("\n");
}
return 0;
}
Why Is This Factorial Algorithm Not Accurate
There's nothing wrong in your algorithm as such. It is just that the data types you use have a limit for the highest number they can store. This will be a problem no matter which algorithm you choose. You can change the data types from float to something like long double to hold something bigger. But eventually it will still start failing once the factorial value exceeds the capacity of that data type. In my opinion, you should put an a condition in your factorial function to return without calculating anything if the passed in argument is greater than a value that your chosen datatype can support.
float can represent a wider range of numbers than int, but it cannot represent all the values within that range - as you approach the edge of the range (i.e., as the magnitudes of the values increase), the gap between representable values gets wider.
For example, if you cannot represent values between 0.123 and 0.124, then you also cannot represent values between 123.0 and 124.0, or 1230.0 and 1240.0, or 12300.0 and 12400.0, etc. (of course, IEEE-754 single-precision float gives you a bit more precision than that).
Having said that, float should be able to represent all integer values up to 224 exactly, so I'm going to bet the issue is in the printf call - float parameters are "promoted" to double, so there's a representation change involved, and that may account for the lost precision.
Try changing the return type of factorial to double and see if that doesn't help.
<gratuitous rant>
Every time I see a recursive factorial function I want to scream. Recursion in this particular case offers no improvement in either code clarity or performance over an iterative solution:
double fac( int x )
{
double result = 1.0;
while ( x )
{
result *= x--;
}
return result;
}
and can in fact result in worse performance due to the overhead of so many function calls.
Yes, the definition of a factorial is recursive, but the implementation of a factorial function doesn't have to be. Same for Fibonacci sequences. There's even a closed form solution for Fibonacci numbers
Fn = ((1 + √5)n - (1 - √5)n) / (2n * √5)
that doesn't require any looping in the first place.
Recursion's great for algorithms that partition their data into relatively few, equal-sized subsets (Quicksort, tree traversals, etc.). For something like this, where the partitioning is N-1 subsets of 1 element? Not so much.
</gratuitous rant>

Division issues in C

I don't really know how to explain this (that's why the title was to vague) but I need a way to make C divide in a certain way, I need to make c divide without any decimals in the answer (besides the remainder) for example;
Instead of 5.21 / .25 = 20.84
I need this 5.21 / .25 = *20* Remainder = *.21*
I found out how to find the remainder with Fmod() but how do I find the 20?
Thanks ~
how about using implicit casts?
float k = 5.21 / .25;
int n = k;
k -= n;
results in
k = .84
n = 20
using only ints will also do the job if you don't need the remainder
int k = 5.21 / .25
will automatically truncate k and get k = 20
Use double modf(double value, double *iptr) to extract the integer portion of a FP number.
The modf functions break the argument value into integral and fractional parts, each of which has the same type and sign as the argument. C11 §7.12.6.12 2
#include <math.h>
#include <stdio.h>
int main() {
double a = 5.21;
double b = 0.25;
double q = a / b;
double r = fmod(a, b);
printf("quotient: %f\n", q);
printf("remander: %f\n", r);
double ipart;
double fpart = modf(q, &ipart);
printf("quotient i part: %f\n", ipart);
printf("quotient f part: %f\n", fpart);
return 0;
}
Output
quotient: 20.840000
remander: 0.210000
quotient i part: 20.000000
quotient f part: 0.840000
Using int is problematic due to a limited range, precision and sign issues.

Dividing 1/n always returns 0.0 [duplicate]

This question already has answers here:
C program to convert Fahrenheit to Celsius always prints zero
(6 answers)
Why does division result in zero instead of a decimal?
(5 answers)
Closed 4 years ago.
I am trying to calculate p1=(1/1)*(1/2)*...*(1/n) but something is wrong and the printf gives me 0.000...0
#include <stdio.h>
int main(void) {
int i,num;
float p3;
do {
printf ("give number N>3 : \n" );
scanf( "%d", &num );
} while( num <= 3 );
i = 1;
p3 = 1;
do {
p3=p3*(1/i);
printf( "%f\n",p3 );
} while ( i <= num );
printf("\nP3=%f",p3);
return 0;
}
(1/i)
i is an int, so that's integer division, resulting in 0 if i > 1. Use 1.0/i to get floating point division.
1 is an integer, i is an integer. So 1/i will be an integer, ie the result will be truncated. To perform floating-point division, one of the operands shall be of type float (or, better, of type double):
p3 *= 1. / i;
I had the same issue. The basic case:
when you want to get float output from two integers, you need to convert one into float
int c = 15;
int b = 8;
printf("result is float %f\n", c / (float) b); // result is float 1.875000
printf("result is float %f\n", (float) c / b); // result is float 1.875000

Problem finding the local maximum of a function in C

I'm designing an algorithm to define a simple method able to find the local maximum of a function f (x) given in an interval [a, b]
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define PI 3.141592653
float funtion_(float a, float x){
float result=0;
result = a * (sin (PI*x));
return result;
}
int main (){
double A = 4.875; //average of the digits of the identification card
double a = 0.0, b =1.0; //maximum and minimum values of the interval [a, b]
double h=0;
double N;
double Max, x;
double sin_;
double inf;
printf ("input the minux value: ");
scanf ("%lf", &inf);
printf ("input the N value: ");
scanf ("%lf", &N);
h= (b-a)/N;
printf("h = %lf\n", h);
x=a-h;
Max = -inf;
do {
x = x+h;
sin_ = funtion_(A, x);
if (sin_>=Max){
Max = sin_;
}
}while (x==b);
printf ("Maximum value: %lf.5", Max);
return 0;
}
The algorithm implements the function f (x) = A * sin (pi * x), where A is the average of the digits of my ID, and inf variable is assigned a number sufficiently greater than the values ​​reached by the function in the interval [a, b] = [0.1].
The algorithm must find the local maximum of the function but it is the maximum returns always zero. do not understand why. What problem may be the logic of my solution?, this problem can be solved by this simple algorithm or some optimization by backtracking is necessary ? Thanks for your responses.
Several problems with this code; probably the most glaring is:
int a = 0, b = 1;
float Max, x;
/* ... */
do {
/* ... */
} while (x == b);
You cannot compare an int and a float for equality. It might work once in a great while due to dumb luck :) but you cannot expect this code to function reliably.
I strongly recommend changing all your int variables to double, all your float variables to double, and all the scanf(3) and printf(3) calls to match. While you can combine different primitive number types in one program, and even in one expression or statement, subtle differences in execution will take you hours to discover.
Furthermore, comparing floating point formats for equality is almost never a good idea. Instead, compare the difference between two numbers to a epsilon value:
if (fabs(a-b) < 0.001)
/* consider them equal */
You might want to scale your epsilon so that it matches the scale of your problem; since float really only supports about seven digits of precision, this comparison wouldn't work well:
if (fabsf(123456789 - 123456789.1) < 0.5)
/* oops! fabsf(3) used to force float */
/* and float can't tell the difference */
You might want to find a good introduction to numerical analysis. (Incidentally, one of my favorite classes back in school. :)
update
The core of the problem is your while(x == b). I fixed that and a few smaller problems, and this code seems to work:
#include
#include
#include
#define PI 3.141592653
float funtion_(float a, float x)
{
float result = 0;
result = a * (sin(PI * x));
return result;
}
int main()
{
float A = 4.875; //average of the digits of the identification card
float a = 0.0, b = 1.0; //maximum and minimum values of the interval [a, b]
float h = 0;
float N;
float Max, x;
float sin_;
float inf;
printf("\ninput the inf value: ");
scanf("%f", &inf);
printf("\ninput the N value: ");
scanf("%f", &N);
h = (b - a) / N;
x = a - h;
Max = -inf;
do {
x = x + h;
sin_ = funtion_(A, x);
if (sin_ >= Max) {
Max = sin_;
printf("\n new Max: %f found at A: %f x: %f\n", Max, A, x);
}
} while (x < b);
printf("Maximum value: %.5f\n", Max);
return 0;
}
Running this program with some small inputs:
$ ./localmax
input the inf value: 1
input the N value: 10
new Max: 0.000000 found at A: 4.875000 x: 0.000000
new Max: 1.506458 found at A: 4.875000 x: 0.100000
new Max: 2.865453 found at A: 4.875000 x: 0.200000
new Max: 3.943958 found at A: 4.875000 x: 0.300000
new Max: 4.636401 found at A: 4.875000 x: 0.400000
new Max: 4.875000 found at A: 4.875000 x: 0.500000
Maximum value: 4.87500
$
You are doing your calculations, in particular the initialisation of h, with integer arithmetic. So in the statement:
h = (b-a) / N;
a, b, and N are all integers so the expression is evaluated as an integer expression, and then converted to a float for assignment to h. You will probably find that the value of h is zero. Try adding the following line after the calculation of h:
printf("h = %f\n", h);
After you've fixed that by doing the calculations with floating point, you need to fix your while loop. The condition x = b is definitely not what you want (I noticed it was originally x == b before your formatting edit, but that's not right either).
Should the while condition be: while(x <= b)
while (x = b);
There is no way to exit the loop. b is always 1.

Resources