1. ## Type casting

I have a prime number calculator program that uses type casting. The type casting occurs in my "prime_calculator" function, under "Discard remaining composite numbers".

If I run it without type casting it, I get an error msg "conversion from double to unsigned long; possible loss of data".

I was just wondering where/what is the "double"?

mw

Code:
```#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<malloc.h>

/*

This program calculates prime numbers using the Eratosthenes Sieve algorithm.  It will find the prime numbers between 2 & "max".  It overwrites the prime numbers to the file "prime_numbers.txt"
in the same folder.

Definitions:

1) Prime Number: a number with only 2 divisibles (itself & 1); the number "1" is not considered a prime number in this program
2) Composite Number: a number with more than 2 divisibles

Variable key:

discard = this is used to calculate composite numbers
count = a variable I use to count with
prime[max] = a pointer array that stores all of the numbers in the "max" range
max = the maximum range of prime numbers to calculate
highest = input from the user that is passed to "max"

An in-depth explanation of the Eratosthenes Sieve can be found on the internet.

*/

//prototypes
void start (void);
void prime_calculator (unsigned long max);

int main (void)
{
start ();

return 0;
}

void start (void)
{
unsigned long highest;

do
{
//input from user
printf ("\nType '0' to quit.");
printf ("\n\nPlease specify a max range to calculate prime numbers (up to 9000011).\n");
scanf ("%d", &highest);

//check input from user
if (highest < 0 || highest == 1 || highest > 9000011)
{
printf ("\n(Setting max range to 100)\n\n");
highest = 100;
}

//if user doesn't enter zero, call prime_calculator
if (highest != 0)
{
prime_calculator (highest);
}

} while (highest != 0);
}

void prime_calculator (unsigned long max)
{

unsigned long count;

//Open & overwrite file for output
FILE *fp = fopen ("prime_numbers.txt", "w");

//Initialize the array
int *prime = malloc ((max+1)*sizeof(*prime));

if (!prime)
{
puts ("\n\nERROR! Not enough Memory!\n\n");
exit (1);
}

//initialize prime[max]
for (count = 0; count <= max; count++)
{
prime[count] = 1;
}

count = 0;
printf ("\nFinished initializing array.");

{
}

count = 3;

do
{
{
{
}
}
count++;
} while (pow(count,2) <= max);
count = 0;

//Output
printf ("\n\nPrime Numbers between 2 and %d...\n", max);
for (count = 2; count <= max; count++)
{
if (prime[count] == 1)
{
printf ("%d ", count);
fprintf (fp,"\t%d", count);
}
}
count = 0;
fclose (fp);
free (prime);
printf ("\n\n");
}```

2. I'm ........ at math, but I'll give it my best shot - someone please correct me

discard is long, and you're casting the return value of pow to and int (the same effect as abs()?). This would cause the loss of everything after the decimal place?

Always willing to learn

I think the double occurs when you pow count?

3. Just pay attention to the return values of the functions you use. pow's man page

Quzah.

4. I hope I'm not using decimals in prime number calculations... :-)

Ok, I changed the type casting to (unsigned long) and still don't get any errors. I guess what I'm really wondering is why do I have to type cast at all?

'count' is already declared as an unsigned long so it seems redundant to have to type cast it as the same data type when I take it to a power...

mw

5. Oh, I get it! The 'pow' function assumes a double data type. I would need to use 'powl' to get a long double data type (which I guess is as close as I'll get).

My program will calculate prime numbers up to 9000011 (which is near the limit of my computer). Why was I able to type cast the 'pow' function as an 'int' and still get accurate calculations? I didn't verify all 900011 of the prime numbers, but I randomly verified the high-level numbers and they seemed to be correct.

C is quite a bit too fast and loose for me... :-(

mw

6. Casting a floating point number to an integeral type will truncate anything past the decimal place, assuming the rest of the number is in range to fit in the integeral type.

Quzah.

7. Ok, I understand the concept of truncation, but I thought 'unsigned long' has a range of 0 to 4,294,967,295. I chose this data type because I wanted integer numbers that were greater than zero (ie: no decimals and no negative numbers).

What am I missing? And why does using an 'int' data type give me correct calculations when it SHOULD be truncating? I just noticed that my pointer array is an 'int'?! An 'int' pointer array that has over 9 million elements should have some kind of truncation, right?

mw

PS: Why are you guys mentioning "everything past the decimal"? I'm not using decimals at all... ('powf' is a floating point, but that's not in my program)

8. Originally Posted by Lionmane
PS: Why are you guys mentioning "everything past the decimal"? I'm not using decimals at all... ('powf' is a floating point, but that's not in my program)
No one said anything about powf. We've already told you more than once, and even provided a link. You still aren't paying attention:

pow returns a double And you most definately are using that in your program:
Code:
```do
{
{
{
}
}
count++;
} while (pow(count,2) <= max);```

Quzah.

9. Ok, I can understand that.

That still doesn't answer why I can declare '*prime' as an int and have over 9 million elements without any problems. Or why I can typecast 'pow' as an int (using calculations in the millions) without any data loss.

The problem I'm having is not that I'm getting errors; it's that I'm NOT getting errors when I think I should be.

mw

10. That still doesn't answer why I can declare '*prime' as an int and have over 9 million elements without any problems.
If malloc doesn't fail, then it has allocated the space you've requested. If it fails, it hasn't. If it hasn't, and you've requested a huge amount of space, it simply means you either have enough ram, or enough swap space, or a combination of both, for the allocation.

There's no real limitation as far as the C language itself goes on what you're allowed to try and allocate in a single chunk. The only limitation is your hardware, and I suppose that of the data type. (You can't try and allocate 500,000,000,000,000,000,000,000,000,000,000,000,00 0,000,000 objects, because that doesn't fit in the data type (size_t). If nine million fits in size_t, and you've got enough resources, it'll allocate nine million bytes (or objects or whatever). Why shouldn't it work if it meets the above requirements?
Or why I can typecast 'pow' as an int (using calculations in the millions) without any data loss.
Of course there's going to be data loss. What do you expect to happen to anything past the decimal point? Integers don't have decimal places. It has to go some place, so it's lost in the assignment.

Quzah.

11. FWIW
Code:
```#include <stdio.h>
#include <limits.h>

int main()
{
double value  = INT_MAX - 1.0 / 3.0;
int    result = value; /* truncates fractional portion */

printf("INT_MIN   = %11d, ",  INT_MIN);
printf("INT_MAX   = %11d, ",  INT_MAX);
printf("UINT_MAX  = %11u\n",  UINT_MAX);
printf("LONG_MIN  = %11ld, ", LONG_MIN);
printf("LONG_MAX  = %11ld, ", LONG_MAX);
printf("ULONG_MAX = %11lu\n", ULONG_MAX);

printf("value = %18.6f, result = %11d\n", value, result);

value  = INT_MIN * 10.0 / 3.0;
result = value; /* value not representable in an int */

printf("value = %18.6f, result = %11d\n", value, result);

return 0;
}

/* my output
INT_MIN   = -2147483648, INT_MAX   =  2147483647, UINT_MAX  =  4294967295
LONG_MIN  = -2147483648, LONG_MAX  =  2147483647, ULONG_MAX =  4294967295
value =  2147483646.666667, result =  2147483646
value = -7158278826.666667, result =  1431655766
*/```

12. Guys, I appreciate the info but I'm *not* using decimals (regardless of which data type 'pow' is). My calculations do not produce decimals, so truncation to the right of the decimal doesn't matter.

According to my reference book, an 'int' data type has a range of -32,767 to 32,767. So how am I able to calculate numbers in the millions with an 'int' data type without any problems?

This is the type of truncation I was referring to (in QBasic it would truncate anything past the leftmost range).

mw

13. Originally Posted by Lionmane
According to my reference book, an 'int' data type has a range of -32,767 to 32,767. So how am I able to calculate numbers in the millions with an 'int' data type without any problems?
Try the code I posted above to see what your actual implementation limits are.

Also, whether or not the double value calculated by pow is representable as an int is an issue.
Code:
```#include <stdio.h>
#include <limits.h>
#include <math.h>

int main()
{
double power;
for (power = 2; power < 40; power += 2)
{
double value  = pow(2.0, power);
int    result = value; /* truncates fractional portion */
printf("value = %15.0f, result = %d\n", value, result);
}
return 0;
}

/* my output
value =               4, result = 4
value =              16, result = 16
value =              64, result = 64
value =             256, result = 256
value =            1024, result = 1024
value =            4096, result = 4096
value =           16384, result = 16384
value =           65536, result = 65536
value =          262144, result = 262144
value =         1048576, result = 1048576
value =         4194304, result = 4194304
value =        16777216, result = 16777216
value =        67108864, result = 67108864
value =       268435456, result = 268435456
value =      1073741824, result = 1073741824
value =      4294967296, result = 0
value =     17179869184, result = 0
value =     68719476736, result = 0
value =    274877906944, result = 0
*/```

14. >an 'int' data type has a range of -32,767 to 32,767
That's a minimum required range. Chances are very good that you're on a 32-bit system, where the range of int is just over four billion. If you want to be strictly portable then you can use long int, which is required to be at least 32-bits.

15. Thanks Dave!

mw