Thread: Type casting

  1. #16
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by Lionmane
    That still doesn't answer why I can declare '*prime' as an int and have over 9 million elements without any problems.
    Presumably because your machine has enough memory to ensure the malloc() call succeeds. If the malloc() call failed -- and it can fail if there isn't enough free memory -- you will have all sorts of problems. That's one reason why most people terminate if malloc() returns NULL.

    The other related factor is that the range of integers supported on your machine (represented by macros like INT_MAX) is presumably large enough to be able to represent values within the range you're working in.

    Quote Originally Posted by Lionmane
    Or why I can typecast 'pow' as an int (using calculations in the millions) without any data loss.
    That is the result of what values can be represented in an int, and what can be represented in a double. An int is typically 4 bytes, and a double is typically 8. Depending on how the two types are implemented (by your compiler, which may do it based on how your operating system does it, which [in turn] may do it based on how your hardware does it), it is not impossible that every possible value that can be represented in an int can be represented precisely in a double ON YOUR MACHINE. As the range of values that can be represented in an int and a double are implementation dependent, it is also quite possible the conversion from double to int will lose information on another machine. It is also possible (in fact, likely in practice) that it will lose information for large values but not for small ones. That is what your compiler is warning you about.

    Quote Originally Posted by Lionmane
    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.
    A warning is just that: a warning about something which MIGHT happen if the circumstances are right. The typecast does not make the possible loss of precision go way - it just stops the compiler compiler warning about it (as a typecast is essentially an instruction to the compiler of "I know what I'm doing; don't complain about this".

    Incidentally, rather than using "pow(count, 2)", why not use "count*count" or (if the resultant value may be larger than can be stored in an int), use "(long)count*count"?

  2. #17
    Registered User
    Join Date
    May 2005
    Posts
    207
    Ok, so here's the final question:

    Why is using powers in C such an unnecessary hassle? In QBasic, you would simply say:

    for count = (count ^ 2) to max step (count * 2)

    And be done with it. Why does C assume a particular data type for powers anyway? What idiot came up with that idea? Why can't the data type be defined by the user?

    mw

  3. #18
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Historical. Originally there was an intent to keep the core language relatively simple and implement more advanced functionality in library functions. There was also an intent that the standard library could be written in C if desired. The language also does not support overloading of functions (by which I mean two functions of the same name, but working on different type arguments and returning a different type result), so there had to be a family of functions like pow, powl, to support different types.

    There was also an intent, going way back, that C would be the language for systems programming (eg you could write an operating system in C). One characteristic of operating systems is that most of them can be implemented without doing anything in floating point [in fact, the only things most operating systems support that are related to floating point are features so that user programs can do things in floating point]. Hence not much effort was put into supporting anything to do with floating point in C. This is the reason for various "features" such as promoting a float to a double whenever it is passed as a function argument --- the attitude was that, if someone was silly enough to do floating point, they would want maximum precision.

    The result of this was a language with good support for operations on integral types (bit fiddling, arithmetic operations, etc) without much reliance on the standard library, while almost everything non-trivial with floating point types relies on functions in the standard library.

    A result of this is that very few people who are serious about numerical analysis will use C. People who are serious about numerical analysis want to know that an operation on lower precision types (eg float) will be consistently performed in that lower precision. The reason is that such actions by the compiler make it significantly more difficult to analyse algorithms to ensure the algorithm is stable (i.e. it converges on an end result) or to evaluate how long the algorithm will take to produce a result of specified precision. In major numerical codes (that run for several months, even on modern high end machines) the differences of speed and precision become significant. The focus of C on higher precision for floating point comes at the expense of being able to control program speed and memory usage (lower precision types use less memory and [although this isn't always true on modern machines] often execute more quickly). This is the reason that professional numerical analysts will use other languages designed for the purpose.

    C++ does things slightly better (eg a function that accepts a float argument doesn't receive a double behind the scenes in C++), and the recent 1999 C standard addresses a number of the shortcomings of earlier versions of C in this regard. The way it does this involves a mix of additional features in the core language and some additions to the standard library to do things better. One side effect of this is that a C99 standard library (and functionality in some of the standard headers) can no longer be implemented in standard C -- those features rely on some form of "compiler magic" (by which I mean the compiler does things that cannot be programmed directly in standard C) or writing specialised code in some other language.

    The bottom line is that, if you're doing things in C that involve floating point types in any way, you're poking at the less well thought out parts of the language and standard library.
    Last edited by grumpy; 08-18-2005 at 05:54 PM.

  4. #19
    aoeuhtns
    Join Date
    Jul 2005
    Posts
    581
    Quote Originally Posted by Lionmane
    Ok, so here's the final question:

    Why is using powers in C such an unnecessary hassle? In QBasic, you would simply say:

    for count = (count ^ 2) to max step (count * 2)

    And be done with it. Why does C assume a particular data type for powers anyway? What idiot came up with that idea? Why can't the data type be defined by the user?

    mw
    C operators generally map to processor instructions. Processors can add, multiply, bit-shifting, xor, etc, if you instruct them to do so. Most do not have an "exponent" instruction.

    Also, there are different types of exponentiation algorithms that can be used -- for floating point numbers, you would use logarithms, while exact exponents with integers might be implemented via a recursive function. An exponent operator would not fit in with the rest of the operators, since it would map to a function call, not a processor instruction. And since there are multiple ways of doing exponentiation, the function it maps to might not be the type of algorithm that users want.

    After all, if the language supports taking floating point powers, then it implicitly supports taking logarithms, as well. What kind of sick low-level programming language would have logarithms hidden behind one of its operators? And if it supports logarithms, then why isn't a log function also part of the programming language?

    In short, when it comes to C, exponentiation is something best left for the standard library. Adding an operator for it would be a mistake.
    Last edited by Rashakil Fol; 08-18-2005 at 06:39 PM.

  5. #20
    Registered User
    Join Date
    May 2005
    Posts
    207
    Ok, here's my new program. I've removed a couple of libraries (math.h & stdlib.h), toned down my data types and simplified my math for this retarded child.

    I can calculate approx 150% more prime numbers now without having to wait too long (ie: more than about 5 mins). The algorithm I'm using is extremely efficient, but creating a pointer with millions of elements is taxing.

    Any ideas? I was thinking of using a random access file as storage instead of a pointer. I can probably reach the limits of 'int' that way! :-)

    mw
    Code:
    #include<stdio.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 positive integer 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:
    
    highest = input from the user that is passed to "max"
    max = the maximum range of prime numbers to calculate
    prime[max] = a pointer array that stores all of the numbers in the "max" range
    discard = this is used to calculate composite numbers
    count = a variable I use to count with
    
    An in-depth explanation of the Eratosthenes Sieve can be found on the internet.
    
    */
    
    //prototypes
    void start_prime (void);
    int prime_calculator (int max);
    
    int main (void)
    {
    	start_prime ();
    
    	return 0;
    }
    
    void start_prime (void)
    {
    	int highest;
    
    	do
    	{
    		//Input from user
    		printf ("\n\n*WARNING*  Enter '0' to quit if you don't want to overwrite your output file!!");
    		printf ("\n\nPlease specify a max range to calculate prime numbers (up to 21,000,000).\n");
    		scanf ("%d", &highest);
    
    		//Weed killer
    		if (highest < 0 || highest == 1 || highest > 21000000)
    		{
    			printf ("\n(Setting max range to 100)\n");
    			highest = 100;
    		}
    		
    		//Call prime_calculator function
    		if (highest != 0)
    		{
    			prime_calculator (highest);
    		}
    
    	} while (highest != 0);
    	printf ("\n");
    }	
    
    int prime_calculator (int max)
    {
    	int discard;
    	int count;
    
    	//Open and overwrite file for output
    	FILE *fp = fopen ("prime_numbers.txt", "w");
    
    	//Declare pointer array
    	int *prime = malloc ((max+1)*sizeof(*prime));
    
    	if (!prime)
    	{
    		puts ("\n\nERROR! Not enough Memory!\n\n");
    		return (0);
    	}
    	printf ("\nFinished declaring pointer array (step 1 of 4)...");
    
    	//Initialize pointer array
    	prime[0] = 0;
    	prime[1] = 0;
    	for (count = 2; count <= max; count++)
    	{
    		prime[count] = 1;
    	}
    	count = 0;
    	printf ("\n\nFinished initializing pointer array (step 2 of 4)...");
    
    	//Discard even numbers
    	for (discard = 4; discard <= max; discard = discard + 2)
    	{
    		prime[discard] = 0;
    	}
    	discard = 0;
    	printf ("\n\nFinished even discards (step 3 of 4)...");
    
    	//Discard remaining composite numbers using the Eratosthenes Sieve
    	count = 3;
    	do
    	{
    		for (discard = count * count; discard <= max; discard = discard + count * 2)
    		{
    			if (prime[discard] > 0)
    			{
    				prime[discard] = 0;
    			}
    		}
    		count++;
    	} while (count * count <= max);
    	count = 0;
    	discard = 0;
    	printf ("\n\nFinished the Eratosthenes Sieve (step 4 of 4)...");
    
    	//Output and closing for this function call
    	printf ("\n\nPrime Numbers between 2 and %d:\n", max);
    	if (max > 5500)
    	{
    		printf ("** Too many to print on screen! **");
    	}
    	for (count = 2; count <= max; count++)
    	{
    		if (prime[count] == 1)
    		{
    			if (max <= 5500)
    			{
    				printf ("%d ", count);
    			}
    			fprintf (fp,"\t%d", count);
    		}
    	}
    	count = 0;
    	max = 0;
    	free (prime);
    	fclose (fp);
    
    	printf ("\n\n");
    	return (0);
    }
    Last edited by Lionmane; 08-19-2005 at 12:23 PM.

  6. #21
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    I twiddled with some micro-optimizing such as using calloc instead of malloc and the initialization loop (then you need to change your 0/1 logic too). This made it run about twice as fast for my little attempt.

    But as the wisdom goes, it's probably better to improve the algorithm. The Sieve of Atkin is supposed to be an optimized version of the Sieve of Eratosthenes. I found an implementation here, but didn't do much with it.
    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.*

  7. #22
    Registered User
    Join Date
    May 2005
    Posts
    207
    Hey, thanks Dave! That gave me an idea!

    I combined the initialization and the even-number discard loops!

    mw

  8. #23
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Quote Originally Posted by Lionmane
    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.
    Yes you are. I don't care if every single number you produce would fit perfectly in an integer, with nothing past the decimal point. The fact that you are calling a function which returns a floating point number means you are using decimals. If part of your math involves decimals, then you are.

    10.0 is not the same as 10 in C. They're two entirely different data types. If you use 10.0, you're using decimals. Thus, if you use any function wich returns a decimal type, you're now using decimals.

    The reason you get the data loss warning is to let you know, "Hey, if any calculation preformed happens to produce something to the right of the decimal, you're going to lose that."

    It's simply up to you to choose to ignore that or not. Your compiler is just passing the warning along to you in case you aren't understanding. (Which clearly you're not.)


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

  9. #24
    Registered User
    Join Date
    May 2005
    Posts
    207
    Hey Quzah! Seems like you're pretty far behind on this thread... I stopped using those data types a while ago (see my reposted code).

    mw
    Last edited by Lionmane; 08-20-2005 at 08:25 AM.

  10. #25
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    I was clarifying the point that you didn't seem to grasp. If not for your sake, for anyone else who happened along to this thread.


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

  11. #26
    Registered User
    Join Date
    May 2005
    Posts
    207
    You're such a humanitarian. You always post with selfless dedication. Or maybe you just can't find a date...

    I told you to stay out of my threads.

    mw

  12. #27
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Quote Originally Posted by Lionmane
    You're such a humanitarian. You always post with selfless dedication. Or maybe you just can't find a date...

    I told you to stay out of my threads.

    mw
    Personally, I don't care who you think you are, but it's a public forum. The fact of the matter is, you were wrong. If you're too much of a pansy to admit it, and some how it hurts your feelings to be wrong and have it shown, then perhaps it's best you stop posting here. You were wrong. I don't want some one coming along here later taking your incorrect post as correct and making some mistake they can avoid.

    You were wrong. You don't like it, you whine like a ........... That's too bad. You don't like me posting in your threads? Either don't post things that are flat out wrong, or hope some one else catches it before I happen along.

    However, since no one else commented on it after I did, and if they had, you still wouldn't have listened, I did. Again, if I see something is wrong, and no one else is commenting on it, I'm going to point it out. I don't care if it's "your thread". I don't care if you some where told me to keep out of "your threads". I don't really care.

    You were passing off false information as fact, and I corrected it. You don't like it, strive to be better. Start by pulling the stick out of your ass, or getting some thicker skin. You're in a public forum. Expect a public response.

    Oh, and if you still think you're not wrong, go back and read the thread again. This time without being such a wuss, or without wearing your ego on your sleeve, or whatever it is that makes you ........ and moan when you're wrong. Try learning from your mistakes instead of denying they exist.


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

  13. #28
    Registered User
    Join Date
    May 2005
    Posts
    207
    Quote Originally Posted by quzah
    <<snipped something which was never said>>

    Quzah.
    Then I guess you had better hang around, because I can probably teach you a thing or two about women! ;-)

    mw

  14. #29
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Next time you try and attribute things to people which they've never said, try and be less inept at it.
    Closed.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

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