Search code examples
algorithmequationinequality

how do you solve this logarithmic inequality in an efficient way?


The inequality is: nlogn <= a (n is natural number, log is based of 10). Question: what is the maximum value of n possible?

My solution is to scan n = 1 to infinity (step 1) until getting to the point where nlogn > a. Result returned would be n - 1

But I found out that this is not efficient when a is very large. Does anyone have a good idea how to solve it?


Solution

  • I did the algebra for comingstorm's solution properly and made an implementation. On my machine, Newton's method beats binary search by a factor of 4. I have tested newton() on all nonnegative 32-bit integers.

    #include <assert.h>
    #include <limits.h>
    #include <math.h>
    #include <stdio.h>
    #include <time.h>
    
    static int newton(double a) {
        if (a < 2.0 * log10(2.0)) {
            return 1;
        } else if (a < 3.0 * log10(3.0)) {
            return 2;
        }
        double a_log_10 = a * log(10);
        double x = a / log10(a);
        x = (x + a_log_10) / (1.0 + log(x));
        x = (x + a_log_10) / (1.0 + log(x));
        double n = floor(x);
        if (n * log10(n) > a) {
            n--;
        } else if ((n + 1.0) * log10(n + 1.0) <= a) {
            n++;
        }
        return n;
    }
    
    static int binarysearch(double a) {
        double l = floor(a / log10(a));
        double u = floor(a) + 1.0;
        while (1) {
            double m = floor((l + u) / 2.0);
            if (m == l) break;
            if (m * log10(m) > a) {
                u = m;
            } else {
                l = m;
            }
        }
        return l;
    }
    
    static void benchmark(const char *name, int (*solve)(double)) {
        clock_t start = clock();
        for (int a = 1 << 22; a >= 10; a--) {
            int n = solve(a);
            assert(n * log10(n) <= a);
            assert((n + 1) * log10(n + 1) > a);
        }
        printf("%s: %.2f\n", name, (clock() - start) / (double)CLOCKS_PER_SEC);
    }
    
    int main(int argc, char *argv[]) {
        benchmark("newton", newton);
        benchmark("binarysearch", binarysearch);
    }