【问题标题】:Prime number with threading带螺纹的素数
【发布时间】:2016-10-27 14:34:10
【问题描述】:

我写了一个代码来打印用户从头到尾写的所有数字。我想用线程来做到这一点。例如,开始是 1,结束是 100。我要求用户输入一个 N 数字,这是程序创建的线程数。例如,如果他输入 10,程序将创建 10 个线程。第一个线程将打印从 1 到 10 的素数。第二个线程将打印从 10 到 20 的素数。第三个线程将打印从 20 到 30 的素数……

但是我有一个问题。事实上,我的程序在文件中打印了许多不是素数的数字,而且我经常在代码中多次打印相同的数字。

这是我的代码:

void writePrimesToFile(int begin, int end, ofstream&  file)
{
    for (int i = begin; i <= end; i++)
    {
        for (int j = begin; j < end / 2; j++)
        {
            if (i % j != 0)
            {
                file << i << endl;
            }

        }
    }
}

void callWritePrimesMultipleThreads(int begin, int end, string filePath, int N)
{
    ofstream myfile(filePath);
    clock_t startTimer, stopTimer;

    startTimer = clock();

    vector<thread> arr;

    for (int i = 0; i < N; i++)
    {
        int start = begin;
        int finish = N;
        arr.emplace_back(writePrimesToFile, start, finish, ref(myfile));
        start = finish;
        finish += N;
    }
    for (auto& thread : arr)
    {
        thread.join();
    }

    stopTimer = clock();
    cout << "The time that takes is: " << (double)(stopTimer - startTimer) / CLOCKS_PER_SEC << endl;
}

主代码:

    callWritePrimesMultipleThreads(1, 100, "primes2.txt", 10);

【问题讨论】:

  • 您在使用调试器时观察到了什么?
  • if (i % j != 0) 看起来不对
  • @AlgirdasPreidžius 任何可以帮助我解决错误的东西。
  • for (int j = begin; j &lt; end / 2; j++) 是错误的。你应该从j=2开始
  • @RonyCohen 等等,什么?这不是我的问题的答案。您甚至尝试过使用调试器吗?您在使用时观察到了什么?由于调试器是第一个使用的工具,因此当您的代码未按预期运行时。简而言之:您的主要检测算法有缺陷,问题与线程无关。

标签: c++ multithreading


【解决方案1】:

在您的代码中需要解决很多问题,素数将从 1 开始,而不是 0,而且您应该开始除以 2 而不是 1 或 0(您不能除以 0),在您休息 0 之后一,它不是素数,它总是以你要计算的数量结束(10% 20 是没有意义的)

#include <stdio.h>
#include <iostream>
#include <thread>
#include <mutex>
#include <vector>
#include <functional>
#include <fstream>
#include <math.h>

using namespace std;
mutex mtx;

void writePrimesToFile(unsigned int begin, unsigned int end, ofstream& f)
{
    for (unsigned int i = begin; i <= end; i++)
    {
        for (unsigned int j = 2; j < i; j++)
        {
            if (i % j == 0)
            {
                break;
            }
            else if(j + 1 == i)
            {
                mtx.lock();
                f << i << endl;
                mtx.unlock();
            }
        }
    }
}

void callWritePrimesMultipleThreads(unsigned int begin, unsigned int end, string filePath, unsigned int N)
{
    ofstream myfile(filePath);
    clock_t startTimer, stopTimer;

    startTimer = clock();

    vector<thread> arr;
    unsigned int each = end/N;
    unsigned int start = begin;
    unsigned int finish = start + each - 1;
    for (unsigned int i = 0; i < N; i++)
    {
        arr.emplace_back(writePrimesToFile, start, finish, ref(myfile));
        start += each;
        finish += each;
    }
    for (auto& thread : arr)
    {
        thread.join();
    }

    stopTimer = clock();
    cout << "The time that takes is: " << (double)(stopTimer - startTimer) / CLOCKS_PER_SEC << endl;
}


int main()
{
    callWritePrimesMultipleThreads(1, 110, (string)"primes.txt", 10);
    return 0;
}

另外,在写入文件时添加了一个互斥锁。

【讨论】:

  • 谢谢。但我不明白什么是 j+1 == i。为什么你写 else if 而不是简单的 else ?
  • 最后一个要测试的元素是 j+1,如果他到达那里,那是因为所有其他测试都通过并且是素数。
  • 你能不能举个例子,因为我不是很懂
  • 对于 i = 5: j=2 5/2 != 0, j=3 5/3 != 0, j=4 5/4 != 0,没有更多的测试,所以它将写 5 (i) 作为质数。对于 i = 6:j=2 6/2 == 0,6 不是质数并且以 break 结尾。对于 i = 7; j=2 7/2 != 0, j=3 7/3 != 0, j=4 7/4 != 0, j=5 7/5 != 0, j=6 7/6 != 0,没有更多的测试,7 是质数
  • 非常感谢。但是,尽管有互斥体,但数字不是升序,这是否正常,因为您的代码给出了素数但不是升序。
【解决方案2】:

看看你的循环:

for (int i = begin; i <= end; i++)
{
    for (int j = begin; j < end / 2; j++)
    {
        if (i % j != 0)
        {
            file << i << endl;
        }

    }
}

你输出i每次你找到一个不能整除的数字。
这是很多数字。
(例如 9 不能被 2、4、5、6、7 或 8 整除。但它不是质数。)

如果一个数不能被任何数整除 (>=2),则它是质数,如果有任何数不能与它整除,则它不是质数。

beginend / 2之间寻找因子也是不够的,你需要在2sqrt(end)之间寻找。

我的建议是先编写一个有效的单线程素数测试,然后再开始多线程和区间切片。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-28
    • 2011-04-01
    • 2011-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多