1

The question is:

You are given 2 numbers (N , M); the task is to find N√M (Nth root of M).

Input:

The first line of input contains an integer T denoting the number of test cases. Then T test cases follow. Each test case contains two space separated integers N and M.

Output:

For each test case, in a new line, print an integer denoting Nth root of M if the root is an integer else print -1.

Now my solution to this problem was:

#include <math.h>
#include <iostream>
#include <math.h>
using namespace std;

int main() {
    int t;
    float x, p;
    cin>>t;
    for(int i=0;i<t;i++)
    {
        cin>>p>>x;
        if(p==0)
        {
            cout<<"1"<<endl;

        }
        
        else
        {
            float res=pow(x,(1/p));
            cout<<"res="<<res<<endl;
            if(res==int(res))
                cout<<res<<endl;
            else
                cout<<"-1"<<endl;
        }    
    }
    return 0;
}

This caused a problem in the test case :

1
3
1000

Although when I printed res, I got 10 as a result, during the condition checking if(res==int(res)) turned out to be false.

Also I noticed that changing from float res=pow(x,(1/p)); to float res=pow(x,(1.0/p)); was giving the correct answer. I'm guessing its something related to getting 0.33333 when the evaluation of 1/p is done, but I cannot understand why the printed value is 10 but not matching in the condition checking.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • You can minimize your question to "how are `1/p` and `1.0/p` not equal?". – goodvibration Aug 18 '20 at 16:04
  • 2
    To which the answer is obvious - the first one is `float`, the second one is `double`. – goodvibration Aug 18 '20 at 16:05
  • 4
    Does this answer your question? [Is floating point math broken?](https://stackoverflow.com/questions/588004/is-floating-point-math-broken) – EOF Aug 18 '20 at 16:08
  • `1` is a `int`. `1.0` is a `double`. The different types impact the result of the calculation. – Jesper Juhl Aug 18 '20 at 16:09
  • 2
    `1` is of type `int`. If `p` is of type `float`, `1/p` is of type `float` (and evaluated at that precision). `1.0` is of type `double`. If `p` is of type `float`, `1.0/p` is of type `double` (and evaluated at that precision). – EOF Aug 18 '20 at 16:10
  • `if(res==int(res))` -- [Why doesn't my floating point comparison work?](http://www.cs.technion.ac.il/users/yechiel/c++-faq/floating-point-arith.html) – PaulMcKenzie Aug 18 '20 at 16:30
  • This exercise is all about integers (read it again and count how many times it says "integer"). Using `pow` and checking `res==int(res))` might seem like a great idea, but if contest organisers have half a brain collectively, they will give you a test case where it will not work. – n. m. could be an AI Aug 18 '20 at 16:57
  • @n.'pronouns'm. -- All questions from those contest sites should have integer-based solutions. Maybe the rule of thumb for contestants is that: if you're using `pow`, `ceil`, `floor`, `sqrt` or any such floating point function, rethink what you're doing, or just skip the question entirely. Why waste time trying to figure out why your answer of "2.241" doesn't match the sites answer of "2.242"? – PaulMcKenzie Aug 18 '20 at 18:20
  • 1
    The printed value is not equal to the calculated value, the calculated value is not equal to the mathematically correct value. This is floating point arithmetic, in general, all answers are approximations. It's wrong to expect exact results (unless you really know what you are doing). And to echo what others are saying, because of this don't use floating point arithmetic in what is an integer arithmetic problem. – john Aug 18 '20 at 19:30
  • @goodvibration but it didn't explain me why the print statement was giving same values. If the numbers are different, as in values, shouldn't it reflect in print as well? normally, if we compare float and int with same values, dont we get that they are equal – Ankita Paul Aug 19 '20 at 12:26

1 Answers1

4

Why are pow(x,1/p) and pow(x,1.0/p) not equal even though printing their values gives the same result (?)

Computations differ due to precision. Computations are not mathematically exact: pow() did not receive an exact 1/3.

With float p, 1/p can differ from 1.0/p as the first is done using float (or wider) math and the second uses double (or wider) as 1.0 is a double.

This in turn calls either a float or double pow(). Thus there are potentially different res results.

In OP's case: pow(1000.0f,(1/3.0f)) performed a float precision calculation something like pow(1000, near_one_third) and not cbrt(1000.0) - the result was not exactly 10.0f. pow(1000.0f,(1.0/3.0f)) performed a like-wise double precision computation that when rounded to float was exactly 10.0f.

why the printed value is 10 but not matching in the condition checking.

Should res have a computed value a wee more or less than 10.0f, then == is not true.

Print with sufficient precision to see differences in the final output. Recommend at least 9 significant digits for float res.


At a minimum, I suggest using the same floating point types and math throughout. (Use 1.0f with float.) Further recommend to use double.

Final outputs may still not be the exact expected integer (from a math analysis) as pow() though.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • Reinstate Monica I was unaware that printing a value does not always give the precise result. Could you tell me how it works? – Ankita Paul Aug 19 '20 at 12:35
  • @AnkitaPaul All finite floating points values are exact: a [dyadic rational](https://en.wikipedia.org/wiki/Dyadic_rational#In_computing) times some power of 2. How it got that value may involve rounding. See also [Printf width specifier to maintain precision of floating-point value](https://stackoverflow.com/q/16839658/2410359) – chux - Reinstate Monica Aug 19 '20 at 13:11