Prime factorisation in C++ using Fermat's Method - c++

I am currently working on a program in C++, the ultimate goal of which is to display a list of prime factors for a given value, up to the limit of unsigned long int.
It takes advantage of trial division for the first 1000 prime numbers, and uses Fermat's Method of Factorisation for every value thereafter.
Generally, I'd say the program works okay for most numbers I've tested it with, including some larger numbers. However, I seem to have hit a snag with certain numbers. For example, when the prime number 18446744073709551557 is entered, it crashes entirely. For other larger values such as 246819835539726757, it displays the first five prime factors (7, 11, 37, 131, and 557) correctly, but miscalculates the last two, which should be 18379 and 64601.
The code for the function is as follows:
std::list < unsigned long int >primeFactors(unsigned long int n)
{
bool complete = false;
std::list<unsigned long int> factors;
unsigned long int ans1 = 0;
unsigned long int ans2 = 0;
int a;
int b;
// If n is 0 or 1, return a blank list
//
// This is run outside the while loop, as n will never be 0 or 1 after
// the initial calculation
if (n == 0 || n == 1)
{
complete = true;
return factors;
}
while (complete == false)
{
// if n is a prime number, add to the list and return
if (isPrime(n) == true)
{
factors.push_back(n);
complete = true;
return factors;
}
// if n is even (i.e. divisible by 2), add 2 and n/2 to the list and
// return
else if (divisibleByPrime(n) != 0)
{
unsigned long int divisor = divisibleByPrime(n);
ans1 = divisor;
ans2 = n / divisor;
if (isPrime(ans1) == true && isPrime(ans2) == true)
{
factors.push_back(ans1);
factors.push_back(ans2);
complete = true;
return factors;
}
else
{
if (isPrime(ans1) == true)
{
factors.push_back(ans1);
n = ans2;
}
else
{
factors.push_back(ans2);
n = ans1;
}
}
}
else
{
// a is the square root of n + a^2
unsigned long int i = 1;
float squareRoot;
std::stringstream ss;
std::string str;
bool isDouble = true;
bool answerFound = false;
unsigned long int x;
unsigned long int y;
while (answerFound == false)
{
isDouble = false;
squareRoot = (float)sqrt(n + (i * i));
ss << squareRoot;
str = ss.str();
for (char& i : str)
{
if (strchr(".", i) != NULL)
{
isDouble = true;
}
}
if (isDouble == true)
{
ss.str("");
i += 1;
}
else
{
answerFound = true;
}
}
x = (unsigned long int) squareRoot;
y = i;
ans1 = x + y;
ans2 = x - y;
if (isPrime(ans1) == true && isPrime(ans2) == true)
{
factors.push_back(ans1);
factors.push_back(ans2);
complete = true;
return factors;
}
else
{
if (isPrime(ans1))
{
factors.push_back(ans1);
n = ans2;
}
else
{
factors.push_back(ans2);
n = ans1;
}
}
}
}
I have not included functions such as isPrime or divisibleByPrime as both seem to work fine in an isolated environment.
EDIT: I appreciate certain variables are such are a little messy at the minute, but I plan on rectifying that soon.

Related

The next prime number

Among the given input of two numbers, check if the second number is exactly the next prime number of the first number. If so return "YES" else "NO".
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int nextPrime(int x){
int y =x;
for(int i=2; i <=sqrt(y); i++){
if(y%i == 0){
y = y+2;
nextPrime(y);
return (y);
}
}
return y;
}
int main()
{
int n,m, x(0);
cin >> n >> m;
x = n+2;
if(n = 2 && m == 3){
cout << "YES\n";
exit(0);
}
nextPrime(x) == m ? cout << "YES\n" : cout << "NO\n";
return 0;
}
Where is my code running wrong? It only returns true if next number is either +2 or +4.
Maybe it has something to do with return statement.
I can tell you two things you are doing wrong:
Enter 2 4 and you will check 4, 6, 8, 10, 12, 14, 16, 18, ... for primality forever.
The other thing is
y = y+2;
nextPrime(y);
return (y);
should just be
return nextPrime(y + 2);
Beyond that your loop is highly inefficient:
for(int i=2; i <=sqrt(y); i++){
Handle even numbers as special case and then use
for(int i=3; i * i <= y; i += 2){
Using a different primality test would also be faster. For example Miller-Rabin primality test:
#include <iostream>
#include <cstdint>
#include <array>
#include <ranges>
#include <cassert>
#include <bitset>
#include <bit>
// square and multiply algorithm for a^d mod n
uint32_t pow_n(uint32_t a, uint32_t d, uint32_t n) {
if (d == 0) __builtin_unreachable();
unsigned shift = std::countl_zero(d) + 1;
uint32_t t = a;
int32_t m = d << shift;
for (unsigned i = 32 - shift; i > 0; --i) {
t = ((uint64_t)t * t) % n;
if (m < 0) t = ((uint64_t)t * a) % n;
m <<= 1;
}
return t;
}
bool test(uint32_t n, unsigned s, uint32_t d, uint32_t a) {
uint32_t x = pow_n(a, d, n);
//std::cout << " x = " << x << std::endl;
if (x == 1 || x == n - 1) return true;
for (unsigned i = 1; i < s; ++i) {
x = ((uint64_t)x * x) % n;
if (x == n - 1) return true;
}
return false;
}
bool is_prime(uint32_t n) {
static const std::array witnesses{2u, 3u, 5u, 7u, 11u};
static const std::array bounds{
2'047u, 1'373'653u, 25'326'001u, 3'215'031'751u, UINT_MAX
};
static_assert(witnesses.size() == bounds.size());
if (n == 2) return true; // 2 is prime
if (n % 2 == 0) return false; // other even numbers are not
if (n <= witnesses.back()) { // I know the first few primes
return (std::ranges::find(witnesses, n) != std::end(witnesses));
}
// write n = 2^s * d + 1 with d odd
unsigned s = 0;
uint32_t d = n - 1;
while (d % 2 == 0) {
++s;
d /= 2;
}
// test widtnesses until the bounds say it's a sure thing
auto it = bounds.cbegin();
for (auto a : witnesses) {
//std::cout << a << " ";
if (!test(n, s, d, a)) return false;
if (n < *it++) return true;
}
return true;
}
And yes, that is an awful lot of code but it runs very few times.
Something to do with the return statement
I would say so
y = y+2;
nextPrime(y);
return (y);
can be replaced with
return nextPrime(y + 2);
Your version calls nextPrime but fails to do anything with the return value, instead it just returns y.
It would be more usual to code the nextPrime function with another loop, instead of writing a recursive function.

negative palindrome number failure

i need to determine if a number is palindrome or not
ex: 121 yes,
ex: -121 no.
the program seems to work with palindrome numbers however i am having trouble figuring out the negative numbers, and non palindrome numbers
class Solution {
public:
bool isPalindrome(int x) {
int reverse = 0;
int digit;
int n = x;
bool t = true;
while(x > 0){
digit = x%10;
reverse = (reverse*10) + digit;
x = x/10;
}
if (n == reverse) {
return t;
}
else if(n != reverse) {
return -1;
}
return -1;
}
};
bool isPalindrome(int A)
{
int Rev{ 0 } , rem , C{ A };
while( ( abs( A ) ) ! = 0 )
{
rem = ( abs( A ) ) % 10;
Rev = Rev * 10 + rem;
A / = 10;
}
if( C ! = Rev or C < 0)
return false;
else if( C == Rev and C > 0)
return true;
}
Change your if statements with the following and then this works for negative numbers.
Hope this works for you!!
class Solution {
public boolean isPalindrome(int x){
int reverse=0;
int duplicate_x=x;
for(int i=0;i<=x;i++)
{
int r=x%10;
reverse=(reverse*10)+r;
x=x/10;
}
if(x>=1){ **wrote this if condition to catch unit place number**
reverse=(reverse*10)+x;
}
if(reverse==duplicate_x)
{
return true;
}
else
{
return false;
}
}
}
I used for loop because I was getting time exceeding error in leetcode
and has you mention in your question about negative number palindrome I don't get it why should we write code for those negative number palindrome where we know a **negative number cannot be a palindrome number!
Please correct me if I am wrong
int x=121;
if(x<0){
System.out.println("false");
System.exit(0);
}
int div, sum=0;
int res=x;
while(x!=0){
div = x%10;
sum = sum*10 + div;
x=x/10;
}
if(sum==res)
System.out.println("True");
Can't be able to come up with a simple solution more than this one.

Reverse Integer Catch overflow C++

Hello I am trying a simple reverse integer operation in c++. Code below:
#include <iostream>
#include <algorithm>
#include <climits>
using namespace std;
class RevInteger {
public:
int reverse(int x)
{
int result = 0;
bool isNeg = x > 0 ? false : true;
x = abs(x);
while (x != 0)
{
result = result * 10 + x % 10;
x = x / 10;
}
if (isNeg)
result *= -1;
if (result > INT_MAX || result < INT_MIN)
return 0;
else
return (int)result;
}
};
When I give it an input as 1534236469; I want it to return me 0, instead it returns me some junk values. What is wrong in my program. Also, I am trying to use the climits lib for the purpose, is there a simpler way of doing the same?
The simplest approach is to use long long in place of int for the result, and check for overflow at the end:
long long result = 0;
/* the rest of your code */
return (int)result; // Now the cast is necessary; in your code you could do without it
Another approach is to convert the int to string, reverse it, and then use the standard library to try converting it back, and catch the problems along the way (demo):
int rev(int n) {
auto s = to_string(n);
reverse(s.begin(), s.end());
try {
return stoi(s);
} catch (...) {
return 0;
}
}
If you must stay within integers, an approach would be to check intermediate result before multiplying it by ten, and also checking for overflow after the addition:
while (x != 0) {
if (result > INT_MAX/10) {
return 0;
}
result = result * 10 + x % 10;
if (result < 0) {
return 0;
}
x = x / 10;
}
class Solution {
public:
int reverse(int x) {
int reversed = 0;
while (x != 0) {
if (reversed > INT_MAX / 10 || reversed < INT_MIN / 10) return 0;
reversed = reversed * 10 + (x % 10);
x /= 10;
}
return reversed;
}
};
If reversed bigger than 8 digit INT_MAX (INT_MAX / 10), then if we add 1 digit to reversed, we will have an int overflow. And similar to INT_MIN.
As suggested by #daskblinkenlight; changing the result as long long and type casting at the end solves the problem.
Working class:
class intReverse {
public:
int reverse(int x) {
long long result = 0; // only change here
bool isNeg = x > 0 ? false : true;
x = abs(x);
while (x != 0) {
result = result * 10 + x % 10;
x = x / 10;
}
if (isNeg) {
result *= -1;
}
if (result > INT_MAX || result < INT_MIN)
{
return 0;
}
else
{
return (int) result;
}
}
};
int reverse(int x) {
int pop = 0;
int ans = 0;
while(x) {
// pop
pop = x % 10;
x /= 10;
// check overflow
if(ans > INT_MAX/10 || ans == INT_MAX/10 && pop > 7) return 0;
if(ans < INT_MIN/10 || ans == INT_MIN/10 && pop < -8) return 0;
// push
ans = ans * 10 + pop;
}
return ans;
}

Read a float from a file on an SD card using Arduino/C++

I work with Arduino with Eclipse. I want to read a double from a configuration file. I have made these functions:
void Settings::readDouble(char buff, String data, bool flag, double dataToStore) {
data = "";
int intPart = 0;
int probablyFloatPart = 0;
while(buff != '\n') {
if(isdigit(buff)) {
data.concat(buff);
Serial.println(data);
}
else if (buff == '.') {
char charBuf[data.length()+1];
data.toCharArray(charBuf,data.length()+1);
// Convert chars to int
intPart = atoi(charBuf);
Serial.println(intPart);
data="";
flag = false;
}
buff = theSettings.read();
};
// Convert string to array of chars
char charBuf[data.length()+1];
data.toCharArray(charBuf,data.length()+1);
// Convert chars to integer
probablyFloatPart = atoi(charBuf);
Serial.println(probablyFloatPart);
if (!flag) {
dataToStore = intPart + (probablyFloatPart/pow(10, data.length()));
}
else {
dataToStore = probablyFloatPart;
}
flag = true;
//Serial.println(dataToStore, 5);
}
From serial.printing I noticed that if the number I want to read has more than four digits on either int or decimal part it gives an error. Basically, I can not tranform a string with more than four bytes to an int. How can I do this?
You will need to use long to store values over 32767 (or in an unsigned, over 65535).
I'll be back with a simpler piece of code - I think your code is more complex than it needs to be.
This code uses no standard functions except isdigit, and just walks through the number. No limitiation on the size of the number (obviosusly, if you go over the limit for a double, then it will fail). Error handling may need a bit of improvement. I have given it some mild testing...
double str_to_double(const char *data, size_t len)
{
double d = 0.0;
bool neg = false;
int index = 0;
if (data[index] == '-')
{
index++;
neg = true;
}
while(data[index] != '.' && index < len)
{
if (isdigit(data[index]))
{
d = d * 10 + (data[index] - '0');
index ++;
}
else
{
// Handle "bad input" ...
return -1;
}
}
if (data[index] == '.')
{
index ++;
double div = 10.0;
while(index < len)
{
if (isdigit(data[index]))
{
d += (data[index] - '0') / div;
div *= 10;
index++;
}
else
{
// Handle bad input
return -1;
}
}
}
// Flip sign if need be.
if (neg)
{
d = -d;
}
return d;
}
I would try to save the result in a float. The code below is what I would try.
float result = 0;
float scale = 10;
bool pastDecPoint = false;
while(buff != '\n') {
if(isdigit(buff){
if(pastDecPoint)
{
result = result + (buff / scale);
scale = scale * 10;
}
else
{
result = (result * 10.0) + atoi(buff);
}
} else if (buff == '.') {
pastDecPoint = true;
}
buff = theSettings.read();
};
Serial.println(result);
}
I also want to see what petersson comes back with. Which is very similar to Petersson

Perfect square and perfect cube

Is there any predefined function in c++ to check whether the number is square of any number and same for the cube..
No, but it's easy to write one:
bool is_perfect_square(int n) {
if (n < 0)
return false;
int root(round(sqrt(n)));
return n == root * root;
}
bool is_perfect_cube(int n) {
int root(round(cbrt(n)));
return n == root * root * root;
}
sqrt(x), or in general, pow(x, 1./2) or pow(x, 1./3)
For example:
int n = 9;
int a = (int) sqrt((double) n);
if(a * a == n || (a+1) * (a+1) == n) // in case of an off-by-one float error
cout << "It's a square!\n";
Edit: or in general:
bool is_nth_power(int a, int n) {
if(n <= 0)
return false;
if(a < 0 && n % 2 == 0)
return false;
a = abs(a);
int b = pow(a, 1. / n);
return pow((double) b, n) == a || pow((double) (b+1), n) == a;
}
No, there are no standard c or c++ functions to check whether an integer is a perfect square or a perfect cube.
If you want it to be fast and avoid using the float/double routines mentioned in most of the answers, then code a binary search using only integers. If you can find an n with n^2 < m < (n+1)^2, then m is not a perfect square. If m is a perfect square, then you'll find an n with n^2=m. The problem is discussed here
Try this:
#include<math.h>
int isperfect(long n)
{
double xp=sqrt((double)n);
if(n==(xp*xp))
return 1;
else
return 0;
}
The most efficient answer could be this
int x=sqrt(num)
if(sqrt(num)>x){
Then its not a square root}
else{it is a perfect square}
This method works because of the fact that x is an int and it will drop down the decimal part to store only the integer part. If a number is perfect square of an integer, its square root will be an integer and hence x and sqrt(x) will be equal.
For identifying squares i tried this algorithm in java. With little syntax difference you can do it in c++ too.
The logic is, the difference between every two consecutive perfect squares goes on increasing by 2. Diff(1,4)=3 , Diff(4,9)=5 , Diff(9,16)= 7 , Diff(16,25)= 9..... goes on.
We can use this phenomenon to identify the perfect squares.
Java code is,
boolean isSquare(int num){
int initdiff = 3;
int squarenum = 1;
boolean flag = false;
boolean square = false;
while(flag != true){
if(squarenum == num){
flag = true;
square = true;
}else{
square = false;
}
if(squarenum > num){
flag = true;
}
squarenum = squarenum + initdiff;
initdiff = initdiff + 2;
}
return square;
}
To make the identification of squares faster we can use another phenomenon, the recursive sum of digits of perfect squares is always 1,4,7 or 9.
So a much faster code can be...
int recursiveSum(int num){
int sum = 0;
while(num != 0){
sum = sum + num%10;
num = num/10;
}
if(sum/10 != 0){
return recursiveSum(sum);
}
else{
return sum;
}
}
boolean isSquare(int num){
int initdiff = 3;
int squarenum = 1;
boolean flag = false;
boolean square = false;
while(flag != true){
if(squarenum == num){
flag = true;
square = true;
}else{
square = false;
}
if(squarenum > num){
flag = true;
}
squarenum = squarenum + initdiff;
initdiff = initdiff + 2;
}
return square;
}
boolean isCompleteSquare(int a){
// System.out.println(recursiveSum(a));
if(recursiveSum(a)==1 || recursiveSum(a)==4 || recursiveSum(a)==7 || recursiveSum(a)==9){
if(isSquare(a)){
return true;
}else{
return false;
}
}else{
return false;
}
}
For perfect square you can also do:
if(sqrt(n)==floor(sqrt(n)))
return true;
else
return false;
For perfect cube you can:
if(cbrt(n)==floor(cbrt(n)))
return true;
else
return false;
Hope this helps.
We could use the builtin truc function -
#include <math.h>
// For perfect square
bool is_perfect_sq(double n) {
double r = sqrt(n);
return !(r - trunc(r));
}
// For perfect cube
bool is_perfect_cube(double n) {
double r = cbrt(n);
return !(r - trunc(r));
}
bool isSquare(int n) {
return floor(sqrt(n)) == ceil(sqrt(n));
}
bool isQube(int n) {
return floor(cbrt(n)) == ceil(cbrt(n));
}