Thread: Type casting

  1. #1
    Registered User
    Join Date
    May 2005
    Posts
    207

    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 discard;
    	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.");
    
    	//Discard even composite numbers
    	for (discard = 4; discard <= max; discard = discard + 2)
    	{
    		prime[discard] = 0;
    	}
    	discard = 0;
    	printf ("\n\nFinished even discards.");
    
    	//Discard remaining composite numbers
    	count = 3;
    
    	do
    	{
    		for (discard = (int) pow(count,2); discard <= max; discard = discard + count * 2)
    		{
    			if (prime[discard] > 0)
    			{
    				prime[discard] = 0;
    			}
    		}
    		count++;
    	} while (pow(count,2) <= max);
    	count = 0;
    	discard = 0;
    	printf ("\n\nFinished all other discards.");
    
    	//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. #2
    Supermassive black hole cboard_member's Avatar
    Join Date
    Jul 2005
    Posts
    1,709
    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?

    Sorry if it didn't help you, I'd like to know myself.
    Always willing to learn

    I think the double occurs when you pow count?
    Good class architecture is not like a Swiss Army Knife; it should be more like a well balanced throwing knife.

    - Mike McShaffry

  3. #3
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Just pay attention to the return values of the functions you use. pow's man page


    Quzah.
    Hope is the first step on the road to disappointment.

  4. #4
    Registered User
    Join Date
    May 2005
    Posts
    207
    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. #5
    Registered User
    Join Date
    May 2005
    Posts
    207
    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. #6
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    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.
    Hope is the first step on the road to disappointment.

  7. #7
    Registered User
    Join Date
    May 2005
    Posts
    207
    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)
    Last edited by Lionmane; 08-18-2005 at 01:55 PM.

  8. #8
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Quote 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
    	{
    		for (discard = (int) pow(count,2); discard <= max; discard = discard + count * 2)
    		{
    			if (prime[discard] > 0)
    			{
    				prime[discard] = 0;
    			}
    		}
    		count++;
    	} while (pow(count,2) <= max);

    Quzah.
    Hope is the first step on the road to disappointment.

  9. #9
    Registered User
    Join Date
    May 2005
    Posts
    207
    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. #10
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    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.
    Hope is the first step on the road to disappointment.

  11. #11
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    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
    */
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  12. #12
    Registered User
    Join Date
    May 2005
    Posts
    207
    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. #13
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Quote 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.

    [edit]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
    */
    Last edited by Dave_Sinkula; 08-18-2005 at 04:42 PM. Reason: Added code.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  14. #14
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >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.
    My best code is written with the delete key.

  15. #15
    Registered User
    Join Date
    May 2005
    Posts
    207
    Thanks Dave!

    mw

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. What dose this type casting mean??
    By zhoufanking in forum C Programming
    Replies: 4
    Last Post: 06-11-2008, 06:09 AM
  2. Replies: 0
    Last Post: 03-20-2008, 07:59 AM
  3. pointer to array of objects of struct
    By undisputed007 in forum C++ Programming
    Replies: 12
    Last Post: 03-02-2004, 04:49 AM
  4. Erros in Utility Header File
    By silk.odyssey in forum C++ Programming
    Replies: 4
    Last Post: 12-22-2003, 06:17 AM
  5. help with simple type casting problem
    By Jeremy_S in forum C Programming
    Replies: 2
    Last Post: 02-27-2002, 12:38 PM