DEBUG一个算质数程序
  • 板块学术版
  • 楼主坎巴拉
  • 当前回复5
  • 已保存回复5
  • 发布时间2024/8/27 12:30
  • 上次更新2024/8/27 15:22:48
查看原帖
DEBUG一个算质数程序
358070
坎巴拉楼主2024/8/27 12:30
#include <iostream>
#include <vector>
#include <thread>
#include <fstream>
#include <mutex>
#include "BigInt.h"
#include <Windows.h>
#include <deque>
#include <algorithm>

#define KEY_DOWN(vkey) ((GetAsyncKeyState(vkey)&0x8000)?0:1)

using namespace std;

BigInt a, b;
string kfp[1024]; // 保存多个kp文件的路径
ofstream fout;
bool isp;
bool termin;
bool on[1024];
unsigned long long sos[1024], eos[1024];
bool readone[1024];
std::vector<BigInt> kp[1024]; // 多个kp数组
int kp_count = 0; // kp文件的数量
std::vector<BigInt> nbkp;
void checkPrimesInSegment(int i, bool& isp, const std::vector<BigInt>& kp) {
    while (!termin) {
        if (on[i]) {
            for (auto p = sos[i]; p <= eos[i]; p++) {
                if (p >= kp.size()) {
                    cout << "Out of range: p=" << p << " eos[i]=" << eos[i] << " kp.size()=" << kp.size() << "\n";
                    on[i] = 0; // 避免无限循环
                    break;
                }
                BigInt prime = kp[p];
                if (prime * prime > a) {
                    on[i] = 0;
                    break;
                }
                if (a % prime == BigInt("0")) {
                    isp = false;
                    on[i] = 0;
                    break;
                }
            }
            on[i] = 0;
        }
    }
    return;
}

void SetPCC(BigInt a, BigInt b, int thread_count) {
    fout.open("pcc.txt");
    fout << a << " " << b << '\n' << thread_count << '\n';
    for (int i = 0; i < kp_count; i++) {
        if(kfp[i]!="NULL")
            fout << kfp[i] << '\n';
    }
    fout.close();
}

void ReadPrimesFromFile(std::vector<BigInt>& kp, const std::string filename,int i)
{
    std::ifstream fin(filename);
    if (fin.is_open())
    {
        string temp;
        BigInt te, form(0);
        while (fin >> temp)
        {
            te = temp;
            if (te * te > b || te < form)
                break;
            if (i == -1)
            {
                form = te;
                kp.push_back(te);
                continue;
            }
            while (te * te > a)
            {
                if (readone[i])
                    break;
            }
            form = te;
            kp.push_back(te);
         //   cout << "Readone! " << kp.size()<<endl;
            readone[i] = 0;
        }
        fin.close();
    }
}

void mergeKpFiles(std::vector<string>  files) {
    vector<pair<BigInt, BigInt>> ranges(files.size());

    // 获取每个文件的范围
    for (int i = 0; i < files.size(); i++) {
        ifstream fin(files[i]);
        if (fin.is_open()) {
            BigInt first, last;
            string temp;
            fin >> temp;
            first = temp;
            while (fin >> temp) {
                last = temp;
            }
            ranges[i] = make_pair(first, last);
            fin.close();
        }
    }

    // 合并范围重叠的文件
    for (int i = 0; i < files.size(); i++) {
        for (int j = i + 1; j < files.size(); j++) {
            if (ranges[i].second >= ranges[j].first) { // 检查重叠
                vector<BigInt> merged_primes;
                ReadPrimesFromFile(merged_primes, files[j],-1);
                ofstream fout(files[i],ios::app);
                for (auto& jp : merged_primes)
                {
                    if (jp > ranges[i].second)
                        fout << '\n' << jp;
                }
                fout.close();

                remove(files[j].c_str()); // 删除被合并的文件
                ranges[j] = ranges.back();
                ranges.pop_back();
                files[j] = files.back();
                files.pop_back();
                kfp[j] = "NULL";
                kp_count--;
                j--; // 重新检查当前j位的文件
            }
        }
    }
}

void findPrimesInRange(BigInt& a, BigInt b, int thread_count) {
    ofstream ufout("primes.txt", ios::app);
    std::vector<std::thread> threads;

    if (kp[0].size() == 0) {
        for (BigInt i = a; i > 2; i = i - BigInt(2)) {
            bool oldflag = 0;
            for (BigInt j = 3; j * j <= a; j = j + BigInt(2)) {
                if (i % j == 0) {
                    oldflag = 1;
                    break;
                }
            }
            if (oldflag == 0) {
                kp[0].push_back(i);
                break;
            }
        }
    }
    for (int i = 0; i < kp_count; ++i)
    {
        if (kp[i].size() == 0)
        {
         //   cout << i << "readone requested!\n";
            readone[i] = 1;
            while(readone[i]){}
        }

    }
    for (int i = 0; i < thread_count; ++i) {
        threads.emplace_back(checkPrimesInSegment, i, std::ref(isp), std::ref(kp[0]));
    }

    while (a <= b) {
        isp = 1;
        for (auto& np : nbkp)//这个方法稍微有些低效
        {
            if (np * np < a)
                kp[kp_count].push_back(np);
        }
        for (int qwe = 0; qwe < kp_count; qwe++)
        {
            if (!isp)
            {
                a = a + BigInt(2);
                SetPCC(a, b, thread_count);
                break;
            }
            for (int i = 0; i < thread_count; i++)
                on[i] = 0;
            int segment_size = kp[qwe].size() / thread_count;
            for (int i = 0; i < thread_count; ++i) {
                sos[i] = i * segment_size;
                eos[i] = (i == thread_count - 1) ? kp[qwe].size() - 1 : (i + 1) * segment_size;
            }
            
            for (int i = 0; i < thread_count; i++)
                on[i] = 1;

            while (1) {
                if (!isp) {
                    for (int i = 0; i < thread_count; i++)
                        on[i] = 0;
                //    cout << a << " do not pass kp[" << qwe << "] check.\n";
                  //  Sleep(1000);
                    break;
                }
                int count = 0;
                for (int i = 0; i < thread_count; i++) {
                    if (!on[i])
                        count++;
                }
                if (count == thread_count)
                    break;
            }

            if (isp) {
                if (qwe == 0&&kp_count>1)
                {
                    for (BigInt k =3; k < kp[qwe].front() && k * k <= a; k = k + BigInt(2)) {
                        if (a % k == 0) {
                          //  cout << a << " do not pass kp[0]'s front check.\n";
                          //  Sleep(1000);
                            isp = 0;
                            break;
                        }
                    }
                    if (!isp)
                        continue;
                }
                if (qwe == kp_count- 1&&kp_count>1)
                {
                 //   cout << qwe << "called back at pigu!\n";
                    for (BigInt k = kp[qwe].back() + BigInt(2); k * k <= a; k = k + BigInt(2)) {
                        if (a % k == 0) {
                         //   cout << a << " do not pass kp[kp_count]'s back check.\n";
                           // Sleep(1000);
                            isp = 0;
                            break;
                        }
                    }
                    if (!isp)
                        continue;
                }
                if(qwe!=0&&qwe!=kp_count-1)
                {
                  //  cout << kp[qwe].size() << "called back at normal! "<<qwe<<endl;
                    for (BigInt k = kp[qwe-1].back()+BigInt(2); k < kp[qwe].front() && k * k <= a; k = k + BigInt(2)) {
                        if (a % k == 0) {
                       //     cout << a << " do not pass kp["<<qwe<<"]'s front check.\n";
                         //   Sleep(1000);
                            isp = 0;
                            break;
                        }
                    }
                    if (!isp)
                        continue;
                }
                

            }
        }
        if (isp)
        {
         //   cout << a << " PASSED!\n";
            ufout << a << '\n';
            nbkp.push_back(a);
            a = a + BigInt(2);
            SetPCC(a, b, thread_count);
        }
        
    }

    termin = 1;
    for (auto& th : threads) {
        th.join();
    }
    ufout.close();
}

int main() {
    int thread_count;
    ifstream fin("pcc.txt");
    thread RPFF[1024];

    if (fin.is_open()) {
        vector<string> files;
        string ta, tb;
        fin >> ta >> tb;
        a = ta;
        b = tb;

        if (a > b) {
            cout << "Invalid range.\n";
            return 0;
        }

        fin >> thread_count;
        string temp;
        int kfpdei = 0;
        while (fin >> temp) {
            files.push_back(temp);
            kfp[kfpdei] = temp;
            ++kfpdei;
            ++kp_count;
        }
        fin.close();
        mergeKpFiles(files); // 合并重叠的kp文件
     //   Sleep(100000);
        for (int i = 0; i < kp_count; i++)
        {
            RPFF[i] = thread(ReadPrimesFromFile, std::ref(kp[i]), kfp[i],i);
        }
        if (a <= 2 && b >= 2) {
            fout.open("primes.txt");
            fout << 2 << '\n';
            fout.close();
            a = 3;
        }

        if (a % 2 == 0)
            a = a + BigInt(1);
        if (b % 2 == 0)
            b = b - BigInt(1);
        findPrimesInRange(a, b, thread_count);
        for (int i = 0; i < thread_count; i++)
            RPFF[i].join();
    }
    return 0;
}

BigInt.h:

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

class BigInt {
private:
    std::vector<int> digits;
    bool is_negative;

    // Helper function to remove leading zeros
    void removeLeadingZeros() {
        while (digits.size() > 1 && digits.back() == 0) {
            digits.pop_back();
        }
        if (digits.size() == 1 && digits[0] == 0) {
            is_negative = false;
        }
    }

public:
    // Constructors
    BigInt() : is_negative(false) { digits.push_back(0); }
    BigInt(const std::string& number) { *this = number; }
    BigInt(int number) { *this = std::to_string(number); }  // 支持整数初始化
    // Assignment operator
    BigInt& operator=(const std::string& number) {
        digits.clear();
        is_negative = false;
        int start = 0;

        if (number[0] == '-') {
            is_negative = true;
            start = 1;
        }

        for (int i = number.length() - 1; i >= start; --i) {
            if (isdigit(number[i])) {
                digits.push_back(number[i] - '0');
            }
        }

        removeLeadingZeros();
        return *this;
    }

    // Display
    friend std::ostream& operator<<(std::ostream& os, const BigInt& num) {
        if (num.is_negative) {
            os << '-';
        }
        for (int i = num.digits.size() - 1; i >= 0; --i) {
            os << num.digits[i];
        }
        return os;
    }

    // Comparison
    bool operator==(const BigInt& other) const {
        return is_negative == other.is_negative && digits == other.digits;
    }

    bool operator!=(const BigInt& other) const {
        return !(*this == other);
    }

    bool operator<(const BigInt& other) const {
        if (is_negative != other.is_negative) {
            return is_negative;
        }
        if (digits.size() != other.digits.size()) {
            return is_negative ? digits.size() > other.digits.size() : digits.size() < other.digits.size();
        }
        for (int i = digits.size() - 1; i >= 0; --i) {
            if (digits[i] != other.digits[i]) {
                return is_negative ? digits[i] > other.digits[i] : digits[i] < other.digits[i];
            }
        }
        return false;
    }

    bool operator<=(const BigInt& other) const {
        return *this < other || *this == other;
    }

    bool operator>(const BigInt& other) const {
        return !(*this <= other);
    }

    bool operator>=(const BigInt& other) const {
        return !(*this < other);
    }

    // Addition
    BigInt operator+(const BigInt& other) const {
        if (is_negative == other.is_negative) {
            BigInt result;
            result.is_negative = is_negative;
            result.digits.clear();

            int carry = 0, i = 0;
            while (i < digits.size() || i < other.digits.size() || carry) {
                int sum = carry;
                if (i < digits.size()) sum += digits[i];
                if (i < other.digits.size()) sum += other.digits[i];

                result.digits.push_back(sum % 10);
                carry = sum / 10;
                i++;
            }

            result.removeLeadingZeros();
            return result;
        }

        return *this - (-other);
    }

    // Subtraction
    BigInt operator-(const BigInt& other) const {
        if (is_negative == other.is_negative) {
            if (abs() >= other.abs()) {
                BigInt result;
                result.is_negative = is_negative;
                result.digits.clear();

                int borrow = 0, i = 0;
                while (i < digits.size() || i < other.digits.size() || borrow) {
                    int diff = (i < digits.size() ? digits[i] : 0) - (i < other.digits.size() ? other.digits[i] : 0) - borrow;

                    if (diff < 0) {
                        diff += 10;
                        borrow = 1;
                    }
                    else {
                        borrow = 0;
                    }

                    result.digits.push_back(diff);
                    i++;
                }

                result.removeLeadingZeros();
                return result;
            }
            return -(other - *this);
        }

        return *this + (-other);
    }

    // Multiplication
    BigInt operator*(const BigInt& other) const {
        BigInt result;
        result.digits.resize(digits.size() + other.digits.size(), 0);
        result.is_negative = is_negative != other.is_negative;

        for (size_t i = 0; i < digits.size(); ++i) {
            int carry = 0;
            for (size_t j = 0; j < other.digits.size() || carry; ++j) {
                int sum = result.digits[i + j] + digits[i] * (j < other.digits.size() ? other.digits[j] : 0) + carry;
                carry = sum / 10;
                result.digits[i + j] = sum % 10;
            }
        }

        result.removeLeadingZeros();
        return result;
    }

    // Division and Modulo
    BigInt operator/(const BigInt& other) const {
        if (other == BigInt("0")) throw std::runtime_error("Division by zero!");

        BigInt dividend = abs();
        BigInt divisor = other.abs();
        BigInt quotient, remainder;
        quotient.digits.resize(dividend.digits.size(), 0);
        for (int i = dividend.digits.size() - 1; i >= 0; --i) {
            remainder = remainder * 10 + dividend.digits[i];
            int div = 0;
            while (remainder >= divisor) {
                remainder = remainder - divisor;
                ++div;
            }
            quotient.digits[i] = div;
        }

        quotient.is_negative = is_negative != other.is_negative;
        quotient.removeLeadingZeros();
        return quotient;
    }

    BigInt operator%(const BigInt& other) const {
        return *this - (*this / other) * other;
    }

    // Negation
    BigInt operator-() const {
        BigInt result = *this;
        result.is_negative = !is_negative;
        return result;
    }

    // Absolute value
    BigInt abs() const {
        BigInt result = *this;
        result.is_negative = false;
        return result;
    }
    BigInt operator+(int num) const {
        return *this + BigInt(num);
    }

    BigInt operator-(int num) const {
        return *this - BigInt(num);
    }

    BigInt operator*(int num) const {
        return *this * BigInt(num);
    }

    BigInt operator/(int num) const {
        return *this / BigInt(num);
    }

    BigInt operator%(int num) const {
        return *this % BigInt(num);
    }
    bool isPrime(const std::vector<BigInt>& primeArray) const {
        // 如果数小于2,则不是质数
        if (*this < BigInt("2")) return false;

        // 逐一检查 primeArray 中的质数是否是 BigInt 的因子
        for (const auto& prime : primeArray) {
            if (prime * prime > *this) break; // 如果 prime 的平方大于当前数,停止检查
            if (*this % prime == BigInt("0")) return false; // 如果能整除,说明不是质数
        }

        // 如果没有任何质因数能整除,说明是质数
        return true;
    }
};

出现了vecotr越界访问的情况,在Visual Studio 2022环境下编译

2024/8/27 12:30
加载中...