1

I want to view all solution for: X^12≡1(mod27) So I wrote the following C++ program which outputs only 1 even though 8 and 10 are possible values for x too.

Why is that?

#include <iostream>
#include <cmath>

int main() {
    for (int i = 0; i <= 2700000; ++i) {
        if (int(pow(i, 12))% 27 == 1) {
            std::cout << i << std::endl;
        }
    }
    std::cout << "Hello, World!" << std::endl;
    return 0;
}
Algo
  • 21
  • 2
  • 4
    The numbers your are computing are way outside the limits of an integer. – drescherjm Nov 28 '21 at 20:01
  • 2
    Also note that `pow()` returns a `double` and you're prone for rounding inaccuracies. – πάντα ῥεῖ Nov 28 '21 at 20:03
  • 1
    Use different type than int, for example long. – T0maas Nov 28 '21 at 20:03
  • 2
    And `int` is only guaranteed to be able to represent numbers between `-32768` to `32767`, although on most modern platforms, it can represent numbers between `-2,147,483,648` to `2,147,483,647`. You may want to consider using `long long` instead, which is guaranteed to be able to represent `-9,223,372,036,854,775,808` to `9,223,372,036,854,775,807`, but I'm afraid that even that will not be sufficient in your case. Therefore, you will have to either use a [bigint library](https://en.wikipedia.org/wiki/List_of_arbitrary-precision_arithmetic_software) or use `double`. – Andreas Wenzel Nov 28 '21 at 20:06
  • The program is instantly broken by using `pow`. – PaulMcKenzie Nov 28 '21 at 20:49

2 Answers2

1

The inbuild pow() function is not capable of handling so large number. Rather we have to use custom function to achieve that.

Here it is

#include <iostream>
#include <cmath>

long long binpow(long long a, long long b, long long m) {
    a %= m;
    long long res = 1;
    while (b > 0) {
        if (b & 1)
            res = res * a % m;
        a = a * a % m;
        b >>= 1;
    }
    return res;
}

int main() {
    for (int i = 0; i <= 2700000; ++i) {
        if (binpow(i, 12, 27) == 1) {
            std::cout << i << std::endl;
        }
    }
    std::cout << "Hello, World!" << std::endl;
    return 0;
}

You can read more about that function from here: https://cp-algorithms.com/algebra/binary-exp.html

-1

Oh, that's because you're using ints to calculate 12th powers, which are very large numbers. Int can only store numbers up to 2147483647, so use long long ints instead which can be much larger.

I rewrote your code and got this output: 1 8 10 17 19 26 28

#include <iostream>
#include <cmath>

int main()
{
    for (int i = 0; i <= 2700000; ++i)
    {
        long long int power = pow(i, 12);
        int mod = power % 27;
        if (mod == 1)
            std::cout << i << std::endl;
    }

    std::cin.get();
    return 0;
}
  • 3
    A `long long` is only guaranteed to be able to represent numbers up to `9,223,372,036,854,775,807`. This limit will be exceeded as soon as `i` reaches `39`. – Andreas Wenzel Nov 28 '21 at 20:34
  • Yeah, that's for op to keep in mind. But for a quick n easy demonstration long long ints are enough. – Carlos Alberto Flores Arellano Nov 28 '21 at 20:48
  • 2
    This program is instantly broken because of the usage of `pow`. Do not use `pow` to solve integer-based problems. – PaulMcKenzie Nov 28 '21 at 20:49
  • What's the problem with implicit double/int conversion? If there are no decimals to truncate there is no risk of data loss. Sure there are implementations of pow() for ints, but why going through the trouble for such a small program? – Carlos Alberto Flores Arellano Nov 29 '21 at 05:04
  • A double has 53 bits of precision. [https://en.wikipedia.org/wiki/Double-precision_floating-point_format](https://en.wikipedia.org/wiki/Double-precision_floating-point_format) In this problem this is not enough especially because of the first comment. pow() is also not accurate for integers because of truncation, – drescherjm Nov 29 '21 at 14:42
  • Related to pow() not being accurate for integers: [https://stackoverflow.com/questions/22264236/why-does-pow5-2-become-24](https://stackoverflow.com/questions/22264236/why-does-pow5-2-become-24) – drescherjm Nov 29 '21 at 14:49
  • Well, op could just wrap it up in a `round()` or `nearbyint()` and they're good to go. And `pow()` is overloaded with `long double pow (long double base, long double exponent);` So I don't see that lack of precision. – Carlos Alberto Flores Arellano Nov 29 '21 at 21:33