434,786 Members | 1,142 Online + Ask a Question
Need help? Post your question and get tips & solutions from a community of 434,786 IT Pros & Developers. It's quick & easy.

How to tell if a number has decimal places different than 0

 P: n/a Sooner or later everytime I found recreational programming challenges I stumble with how I test if a number is has decimal places differnt than 0? For example if I want to know if a number is a square number (i.e. a number which square root is a positive number as 4, 9, 16 have) I do something like: int square = sqrt(number); if((int)square==square) // number is a perfect square else // number is not a perfect square Is there a function or a language-specific-way to do this? Sep 26 '05 #1
27 Replies

 P: n/a Gaijinco wrote on 26/09/05 : Sooner or later everytime I found recreational programming challenges I stumble with how I test if a number is has decimal places differnt than 0? For example if I want to know if a number is a square number (i.e. a number which square root is a positive number as 4, 9, 16 have) I do something like: int square = sqrt(number); if((int)square==square) // number is a perfect square else // number is not a perfect square Is there a function or a language-specific-way to do this? fmod() -- Emmanuel The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html The C-library: http://www.dinkumware.com/refxc.html "It's specified. But anyone who writes code like that should be transmogrified into earthworms and fed to ducks." -- Chris Dollin CLC Sep 26 '05 #2

 P: n/a Gaijinco wrote: Sooner or later everytime I found recreational programming challenges I stumble with how I test if a number is has decimal places differnt than 0? For example if I want to know if a number is a square number (i.e. a number which square root is a positive number as 4, 9, 16 have) I do something like: int square = sqrt(number); if((int)square==square) // number is a perfect square else // number is not a perfect square Is there a function or a language-specific-way to do this? Language-specific? What do you mean by that? Your test is not perfect because it will fail when square is bigger than the biggest int. This test always works (within the limitations of floating point accuracy). #include [itex] double square = sqrt(number); if (floor(square) == square) // number is a perfect square else // number is not a perfect square john Sep 26 '05 #3

 P: n/a Gaijinco wrote On 09/26/05 16:07,: Sooner or later everytime I found recreational programming challenges I stumble with how I test if a number is has decimal places differnt than 0? For example if I want to know if a number is a square number (i.e. a number which square root is a positive number as 4, 9, 16 have) I do something like: int square = sqrt(number); if((int)square==square) // number is a perfect square .... and the test is a tautology. else // number is not a perfect square Is there a function or a language-specific-way to do this? The code you've shown will (if it doesn't invoke undefined behavior) declare that every number is a perfect square: 1, 2, 3.14, and even -42. To test whether a floating-point number is an integer with no fractional part, you could try if ((int)fpn == fpn) ... This runs into trouble when the magnitude of fpn is large, so large that its value is outside the range of numbers representable as `int'. As an improvement you might try if (fmod(fpn, 1.0) == 0.0) ... This is still vulnerable to the "graininess" of floating-point numbers, which are not mathematical real numbers with infinite precision. You cannot usually expect sqrt(fpn) to be the exact square root of fpn. sqrt(fpn) will be very close to the exact root, but will (in general) be just a little bit different from the true value. There could be several different fpn values for which sqrt(fpn) would deliver exactly the same slightly wrong answer: both sqrt(4.0) and sqrt(4.0 + tiny_number) might produce 2.0 as an answer. If you decide that a number is a perfect square if its computed square root turns out to be an integer, you will erroneously conclude that 4.0+tiny_number is a perfect square. A possibly more thorough test might compute the square root, test whether it's an integer, and then test whether its square equals the original number: double root = sqrt(number); if (fmod(root, 1.0) == 0.0 && root * root == number) .... but even this may have some problems. I am always uneasy when comparing floating-point quantities for exact equality, mostly because fpn's are usually regarded as approximations to begin with. You usually need an "approximately equal" test of some kind, and such a test isn't well suited to the purely yet/no nature of perfect squaredom. For "number-theoretic" calculations you'll usually be much better off using integers of some flavor. If the numbers grow large you may need to resort to a "bignum" package; several are available. -- Er*********@sun.com Sep 26 '05 #4

 P: n/a On Mon, 26 Sep 2005 21:05:09 GMT, in comp.lang.c , John Harrison wrote: (of testing to see if a float is a perfect square) This test always works (within the limitations offloating point accuracy). I'd not be too sure of that. Remember floating point is not an exact representation. double square = sqrt(number);if (floor(square) == square) // number is a perfect squareelse // number is not a perfect square -- Mark McIntyre CLC FAQ CLC readme: ----== Posted via Newsfeeds.Com - Unlimited-Uncensored-Secure Usenet News==---- http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups ----= East and West-Coast Server Farms - Total Privacy via Encryption =---- Sep 26 '05 #5

 P: n/a Mark McIntyre wrote: On Mon, 26 Sep 2005 21:05:09 GMT, in comp.lang.c , John Harrison wrote: (of testing to see if a float is a perfect square)This test always works (within the limitations offloating point accuracy). I'd not be too sure of that. Remember floating point is not an exact representation. That's why I said 'within the limitations of floating point accuracy'. My test always checks if a floating point number is integral. Obviously an integral return from sqrt does not necessarily mean the sqrt parameter was a perfect square. john Sep 26 '05 #6

 P: n/a John Harrison wrote On 09/26/05 17:20,: Mark McIntyre wrote:On Mon, 26 Sep 2005 21:05:09 GMT, in comp.lang.c , John Harrison wrote:(of testing to see if a float is a perfect square) This test always works (within the limitations offloating point accuracy). I'd not be too sure of that. Remember floating point is not an exactrepresentation. That's why I said 'within the limitations of floating point accuracy'. My test always checks if a floating point number is integral. Obviously an integral return from sqrt does not necessarily mean the sqrt parameter was a perfect square. On the machine in front of me right now, sqrt(1.0) and sqrt(1.0000000000000002) both give 1.0 as the root. -- Er*********@sun.com Sep 26 '05 #7

 P: n/a Gaijinco wrote: Sooner or later everytime I found recreational programming challenges I stumble with how I test if a number is has decimal places differnt than 0? For example if I want to know if a number is a square number (i.e. a number which square root is a positive number as 4, 9, 16 have) I do something like: int square = sqrt(number); if((int)square==square) // number is a perfect square else // number is not a perfect square Is there a function or a language-specific-way to do this? using modf, you can test either the integral part or the fractional part. Look askance at any solution that involves ints. #include #include #include #include int main(void) { double x, fp, ip; int loop, cnt; srand(time(0)); for (loop = cnt = 0; cnt < 10; loop++) { x = (int) (100. * rand() / (1. + RAND_MAX)) / 10.; fp = modf(x, &ip); if (ip != x || fp) continue; printf("%4d: x = %g, fractional part (fp) = %g," "integer part (ip) = %g\n" " (ip %s x, fp %s 0)\n", loop, x, fp, ip, (ip == x) ? "==" : "!=", (fp == 0) ? "==" : "!="); cnt++; } return 0; } 1: x = 8, fractional part (fp) = 0,integer part (ip) = 8 (ip == x, fp == 0) 36: x = 0, fractional part (fp) = 0,integer part (ip) = 0 (ip == x, fp == 0) 63: x = 6, fractional part (fp) = 0,integer part (ip) = 6 (ip == x, fp == 0) 70: x = 1, fractional part (fp) = 0,integer part (ip) = 1 (ip == x, fp == 0) 79: x = 5, fractional part (fp) = 0,integer part (ip) = 5 (ip == x, fp == 0) 87: x = 5, fractional part (fp) = 0,integer part (ip) = 5 (ip == x, fp == 0) 128: x = 4, fractional part (fp) = 0,integer part (ip) = 4 (ip == x, fp == 0) 147: x = 1, fractional part (fp) = 0,integer part (ip) = 1 (ip == x, fp == 0) 148: x = 8, fractional part (fp) = 0,integer part (ip) = 8 (ip == x, fp == 0) 162: x = 1, fractional part (fp) = 0,integer part (ip) = 1 (ip == x, fp == 0) Sep 26 '05 #8

 P: n/a > On the machine in front of me right now, sqrt(1.0) and sqrt(1.0000000000000002) both give 1.0 as the root. Am I missing something? What point are you making? john Sep 26 '05 #9

 P: n/a John Harrison writes: [...] #include [itex] double square = sqrt(number); if (floor(square) == square) // number is a perfect square else // number is not a perfect square I suggest that "square" is a really bad name for a variable that hold the result of a call to sqrt(). -- Keith Thompson (The_Other_Keith) ks***@mib.org San Diego Supercomputer Center <*> We must do something. This is something. Therefore, we must do this. Sep 26 '05 #10

 P: n/a Mark McIntyre wrote: I'd not be too sure of that. Remember floating point is not an exact representation. Floating point is exact. Unlike real numbers, it is not continuous. -- Pete Becker Dinkumware, Ltd. (http://www.dinkumware.com) Sep 26 '05 #11

 P: n/a Pete Becker wrote: Mark McIntyre wrote: I'd not be too sure of that. Remember floating point is not an exact representation. Floating point is exact. Unlike real numbers, it is not continuous. In general, *finite precision* floating-point arithmetic is *inexact*. The set real numbers includes irrational numbers which have *no* finite precision digital representation in this universe -- they exist only in the minds of mathematicians. Sep 27 '05 #12

 P: n/a Pete Becker writes: Mark McIntyre wrote: I'd not be too sure of that. Remember floating point is not an exact representation. Floating point is exact. Unlike real numbers, it is not continuous. It depends on how you look at it. A given floating-point representation can be viewed either as an exact value, or as an inexact approximation of any of the infinitely many real numbers close to the exact represented value. The latter, though arguably incorrect, is probably the more common interpretation, especially given things like: double one_third = 1.0/3.0; Integers are usually considered to be exact because they typically aren't thought of as being approximations of nearby numbers; 42 really is 42, not an approximation of 42.0625. -- Keith Thompson (The_Other_Keith) ks***@mib.org San Diego Supercomputer Center <*> We must do something. This is something. Therefore, we must do this. Sep 27 '05 #13

 P: n/a In article E.**************@jpl.nasa.gov writes: Pete Becker wrote: Mark McIntyre wrote: I'd not be too sure of that. Remember floating point is not an exact representation. Floating point is exact. Unlike real numbers, it is not continuous. In general, *finite precision* floating-point arithmetic is *inexact*. I think you misunderstand Pete Beckers meaning. Assuming IEEE, given two operands and an operation, it is precisely predictable what the result is. But I understand you are pretty good at misunderstanding. -- dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131 home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/ Sep 27 '05 #14

 P: n/a John Harrison wrote: On the machine in front of me right now, sqrt(1.0) and sqrt(1.0000000000000002) both give 1.0 as the root. Am I missing something? What point are you making? Just giving a concrete example of the point you made (and snipped): [...] Obviously an integral return from sqrt does not necessarily mean the sqrt parameter was a perfect square. -- Eric Sosman es*****@acm-dot-org.invalid Sep 27 '05 #15

 P: n/a "John Harrison" wrote in message news:uC******************@newsfe5-win.ntli.net... Mark McIntyre wrote: On Mon, 26 Sep 2005 21:05:09 GMT, in comp.lang.c , John Harrison wrote: (of testing to see if a float is a perfect square)This test always works (within the limitations of floating pointaccuracy). I'd not be too sure of that. Remember floating point is not an exact representation. That's why I said 'within the limitations of floating point accuracy'. My test always checks if a floating point number is integral. Obviously an integral return from sqrt does not necessarily mean the sqrt parameter was a perfect square. john I think a lot of the discussion here is assuming the the "number" variable being passed to the sqrt function is a random floating point variable. But, I think he was actually asking about testing _integers_, since no value containing a fractional part could _ever_ be the square of an integer. If we assume that "number" is itself an integer (even if it's stored in a float), then testing if the floor of the result of the sqrt call is equal to the result itself is a perfectly valid choice. The range of integers is sufficently small that there will never be a case where the result of the square root will appear to be exactly an integral number when in fact it is not. And, if we're dealing with a "number" variable that is actually floating point, then it makes sense to first check if that number is itself an integer (using floor or fmod) before testing if it's also the square of an integer. -Howard Sep 27 '05 #16

 P: n/a The issue at hand was that I would normally do this for testing if an integrer was a square number: bool square_number(int number){ if(sqrt(number)==floor(sqrt(number))) return true; else return false; } However "sqrt(number)==floor(sqrt(number))" seemed an awkward way to test it, so I wasn't sure if there was a "clenear" way to do it. "fmod(sqrt(number),1.0)==0.0" seems to be an alternate but it isn't very clean to me. The facts about integers and operations were very intresting! Thank you. Sep 27 '05 #17

 P: n/a On Mon, 26 Sep 2005 21:20:26 GMT, in comp.lang.c , John Harrison wrote: Mark McIntyre wrote: (of comparing an int and a float) I'd not be too sure of that. Remember floating point is not an exact representation.That's why I said 'within the limitations of floating point accuracy'. my point exactly. My test always checks if a floating point number is integral. Well, it checks if the floating point number is integral given your first constraint. Its possible for (int)square <> square, even though 'square' /is/ a square number. As a general rule any expression involving comparison operators and floats should be regarded as /highly/ suspect. -- Mark McIntyre CLC FAQ CLC readme: ----== Posted via Newsfeeds.Com - Unlimited-Uncensored-Secure Usenet News==---- http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups ----= East and West-Coast Server Farms - Total Privacy via Encryption =---- Sep 27 '05 #18

 P: n/a On Mon, 26 Sep 2005 19:31:05 -0400, in comp.lang.c , Pete Becker wrote: Mark McIntyre wrote: I'd not be too sure of that. Remember floating point is not an exact representation.Floating point is exact. Unlike real numbers, it is not continuous. Please exactly represent pi in a float. -- Mark McIntyre CLC FAQ CLC readme: ----== Posted via Newsfeeds.Com - Unlimited-Uncensored-Secure Usenet News==---- http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups ----= East and West-Coast Server Farms - Total Privacy via Encryption =---- Sep 27 '05 #19

 P: n/a Mark McIntyre wrote: On Mon, 26 Sep 2005 19:31:05 -0400, in comp.lang.c , Pete Becker wrote:Mark McIntyre wrote: I'd not be too sure of that. Remember floating point is not an exact representation.Floating point is exact. Unlike real numbers, it is not continuous. Please exactly represent pi in a float. He said, it is not continuous. The point is: a) every float represents a unique real number and does so exactly. b) not every real number has a representation as a float. Of course you can *regard* a real number as an approximation to nearby real numbers. Thus, despite (a) being true, one can regard any double as an approximation to nearby real nubers. [Depending on context, we do the same using intergers: every time I encounter \$250, it actually happens to mean \$249.98+tax.] Best Kai-Uwe Bux Sep 27 '05 #20

 P: n/a "Gaijinco" wrote in message news:11**********************@g43g2000cwa.googlegr oups.com... The issue at hand was that I would normally do this for testing if an integrer was a square number: bool square_number(int number){ if(sqrt(number)==floor(sqrt(number))) return true; else return false; } However "sqrt(number)==floor(sqrt(number))" seemed an awkward way to test it, so I wasn't sure if there was a "clenear" way to do it. No sense computing the square root twice. You could store the result of sqrt() in a float (or double) and compare that against the floor() of itself. There are also integer techniques for testing if a number is a perfect square, but those may not be significantly faster in practice (if that's even an issue). -Howard Sep 27 '05 #21

 P: n/a "Howard" wrote: "Gaijinco" wrote in message if(sqrt(number)==floor(sqrt(number))) No sense computing the square root twice. You could store the result of sqrt() in a float (or double) and compare that against the floor() of itself. Any halfway decent compiler will perform that optimisation for you, and possibly do so even more efficiently than using another variable would. Richard Sep 28 '05 #22

 P: n/a "Richard Bos" wrote in message news:43****************@news.xs4all.nl... "Howard" wrote: "Gaijinco" wrote in message > if(sqrt(number)==floor(sqrt(number))) No sense computing the square root twice. You could store the result of sqrt() in a float (or double) and compare that against the floor() of itself. Any halfway decent compiler will perform that optimisation for you, and possibly do so even more efficiently than using another variable would. Richard Really? Do you know that for sure? That seems like an odd thing to expect of a compiler... optimizing out an explicit function call. I can see how it would be easy enough to implement, given that the compiler writers also wrote the sqrt function and know what it does (provided it hasn't been hidden by a user-defined function of the same name), but I'd still suggest that it's poor coding practice to call a function twice when you only need it called once. Writing poor code because you believe that the optimization step will make it better than well-written code is, well, odd, in my opinion. -Howard Sep 28 '05 #23

 P: n/a Howard wrote: No sense computing the square root twice. You could store the result of sqrt() in a float (or double) and compare that against the floor() of itself. Any halfway decent compiler will perform that optimisation for you, and possibly do so even more efficiently than using another variable would. Richard Really? Do you know that for sure? That seems like an odd thing to expect of a compiler... optimizing out an explicit function call. :-) You should see what some compilers do with the str...() family of functions -- Karl Heinz Buchegger kb******@gascad.at Sep 28 '05 #24

 P: n/a On Wed, 28 Sep 2005, Richard Bos wrote: "Howard" wrote: "Gaijinco" wrote in message if(sqrt(number)==floor(sqrt(number))) No sense computing the square root twice. You could store the result of sqrt() in a float (or double) and compare that against the floor() of itself. Any halfway decent compiler will perform that optimisation for you, and possibly do so even more efficiently than using another variable would. But any halfway decent compiler would perform the same optimization if you used another variable. And if you use another variable, your code will probably work faster even on implementations that /aren't/ halfway decent. Plus it's one fewer place to make a mistake like if(sqrt(number)==floor(sqr(number))) or if(sqrt(number)==floor(sqrt(n))) (admittedly both highly unlikely errors, but I've seen dumber mistakes). So I'd split out the calculation as Howard recommended --- even if not for exactly the same reason. -Arthur Sep 28 '05 #25

 P: n/a In article <43****************@news.xs4all.nl>, Richard Bos wrote: "Howard" wrote: "Gaijinco" wrote in message if(sqrt(number)==floor(sqrt(number))) No sense computing the square root twice. You could store the result of sqrt() in a float (or double) and compare that against the floor() of itself. Any halfway decent compiler will perform that optimisation for you, and possibly do so even more efficiently than using another variable would. However, one shouldn't get in the habit of relying on this. Functions outside the standard (or implementation provided) libraries cannot easily be identified to be pure, so in general, 2nd calls cannot be optimized out. Sep 28 '05 #26

 P: n/a Anonymous 7843 wrote On 09/28/05 13:34,: In article <43****************@news.xs4all.nl>, Richard Bos wrote:"Howard" wrote:"Gaijinco" wrote in messageif(sqrt(number)==floor(sqrt(number)))No sense computing the square root twice. You could store the result ofsqrt() in a float (or double) and compare that against the floor() ofitself.Any halfway decent compiler will perform that optimisation for you, andpossibly do so even more efficiently than using another variable would. However, one shouldn't get in the habit of relying on this. Functions outside the standard (or implementation provided) libraries cannot easily be identified to be pure, so in general, 2nd calls cannot be optimized out. Note that sqrt() is not pure, because it can have the side-effect of setting errno. In C99, it can also raise the "invalid" floating-point exception. -- Er*********@sun.com Sep 28 '05 #27

 P: n/a In article , Eric Sosman wrote: Anonymous 7843 wrote On 09/28/05 13:34,: In article <43****************@news.xs4all.nl>, Richard Bos wrote:"Howard" wrote:No sense computing the square root twice. You could store the result ofsqrt() in a float (or double) and compare that against the floor() ofitself.Any halfway decent compiler will perform that optimisation for you, andpossibly do so even more efficiently than using another variable would. However, one shouldn't get in the habit of relying on this. Functions outside the standard (or implementation provided) libraries cannot easily be identified to be pure, so in general, 2nd calls cannot be optimized out. Note that sqrt() is not pure, because it can have the side-effect of setting errno. In C99, it can also raise the "invalid" floating-point exception. Good point! Sep 28 '05 #28

This discussion thread is closed

Replies have been disabled for this discussion. 