-2

Below is the program I've written to find the exponent of 6, but I this its giving wrong output or I may be wrong somewhere, I'm unable to figure out here.

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int main()
{
    ll t;
    cin>>t;
    cout<<log(t)/log(6)<<"\n";
    cout<<floor(log(t)/log(6))<<"\n";
    cout<<ceil(log(t)/log(6));
    return 0;
}

Input:-

216

Output:-

3

3

4

Since 216 can be written as 6*6*6, so whether there is ceil or floor the output should be 3 in all three cases.

Answering to my own question, this problem can be solved by setting small precision(here up to 2 decimal digits), below is the program for the same.

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int t;
    cin>>t;
    cout<<log(t)/log(6)<<"\n";
    cout<<floor((floor(log(t)/log(6)*100.0)/100.0))<<"\n";
    cout<<ceil((floor(log(t)/log(6)*100.0)/100.0));
    return 0;
}
aksr
  • 322
  • 1
  • 2
  • 11
  • you are not calling `floor` or `ceil` with an `int` parameter, hence the question is unclear. What other output did you expect and why? – 463035818_is_not_an_ai Oct 13 '20 at 11:54
  • 4
    btw `#define ll long long` ... why? Its a slap in the face for everybody reading your code and expecting something readable – 463035818_is_not_an_ai Oct 13 '20 at 11:54
  • 4
    log(t) / log(6) is not exactly 3.0 but something like 3.0000000000001. IEEE754 prevision is hard. – Botje Oct 13 '20 at 11:55
  • 2
    Your problem is that of expectations. You seem to be expecting exact results to infinite precision. That's simply not the case with floating point numbers, or numeric algorithms in general. – StoryTeller - Unslander Monica Oct 13 '20 at 11:56
  • if floor is removed then also the output is same 3 3 4. – aksr Oct 13 '20 at 11:58
  • 2
    Default output precision of floating point types in C++ does not print all digits necessary to uniquely identify the number. Try adding `std::cout << std::setprecision(std::numeric_limits::max_digits10);` before you output the results. –  Oct 13 '20 at 12:03
  • If you want to call floor and ceil for an integer, just call floor and cell for an integer. You can also test calling floor and ceil for a double value "which is an integer", i.e., initialized to the constant 3.0. But you are not doing either. – Daniel Daranas Oct 13 '20 at 12:04
  • 1
    The old guard on this site may well grumble at this type of question, but it is well asked. And the code is tidy (even if it would fail a code review at my shop on at least 5 counts). – Bathsheba Oct 13 '20 at 12:07
  • Thank you everyone I got the problem, setting a small precision would solve it. – aksr Oct 13 '20 at 12:12
  • 2
    @aksr: That's evil. Don't use a floating point implementation for an integer problem. – Bathsheba Oct 13 '20 at 12:13
  • I have to use that to check if it is power of 6 or not. – aksr Oct 13 '20 at 12:17
  • 2
    No you don't. But we're going round in circles here. Cat out! – Bathsheba Oct 13 '20 at 12:20
  • @aksr Could you edit the question to clarify the problem? If I give you a 6 the output should be 1, but what do you expect for 7? And for 35? – Costantino Grana Oct 13 '20 at 12:36
  • @aksr should this work just for 6? – Costantino Grana Oct 13 '20 at 12:40
  • yes, it should work for all positive values, and it should give a same integer value for floor and ceil if the given input number can be represented as t raised to pow 6 otherwise values must be different. It is solved by setting lower precision . Thank you – aksr Oct 13 '20 at 13:05
  • Try this one: `std::cout << (log(216)/log(6)-3) << '\n';`. – Pete Becker Oct 13 '20 at 15:40

2 Answers2

3

The log function - like most floating point calculations - is imprecise. There is often tiny amount of error in the result. In your case, you did not get the exact 3, but some value slightly greater than 3. When you apply ceil or floor to such imprecise result, you may increase or reduce the amount of the error up to a whole number. In this case you increased the error by ceiling the result from nearly correct integer to exactly following integer).

eerorika
  • 232,697
  • 12
  • 197
  • 326
0

If you want to find the exponent of an integer with respect to a given radix, then repeated division and checking the remainder is a good starting point. There are faster ways (related to exponentation by squaring) which you could investigate if you want to squeeze out more performance.

The problem is that using the ratio of two log calls and truncating that to an int is bound to give you an inexact answer since the result of a log most likely cannot be represented exactly as a floating point value, and the log function itself may not recover the best floating point value possible (neither the C++ standard nor IEEE754 insist on that).

Finally, on #define ll long long, don't do that. It only serves to obfuscate. And #include<bits/stdc++.h> is not portable C++.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • I can do repeated division but time complexity would be more, I wanted to do with logs. – aksr Oct 13 '20 at 12:15
  • 1
    @aksr: Does the time complexity matter? `idiv` is pretty quick you know. At least you'd get the correct answer. – Bathsheba Oct 13 '20 at 12:16