使用 c++ 将 large int 写入磁盘

发布于 2025-01-11 20:48:20 字数 1661 浏览 4 评论 0原文

我有很多 20 字节整数想要写入磁盘。我使用 GMP mpz_class 将它们存储在 ram 中,

我尝试使用以下测试代码,但文件中的 20x 0 不是预期的 00000000 00000000 00000000 00000000 21F882C7

#include <iostream>
#include <fstream>
#include <string>
#include <gmpxx.h>
using namespace std;

int main() {
    mpz_class userId;
    userId="569934535";

    //open user file
    string fileName= "test.bin";
    ofstream mapFile(fileName,ios::binary);

    //save userId
    mpz_class temp=userId;  //copy so original not destroyed(never reused in example but in real life it would)
    unsigned int bytes[20];
    for (unsigned char i=0;i<20;i++) {
        mpz_class t=temp%256;
        bytes[19-i]=t.get_ui();
        temp/=256;
    }
    mapFile.write((char*)&bytes,20);//expecting to write 00000000 00000000 00000000 00000000 21F882C7
    mapFile.close();

    return 0;
}

我是新的到 c++ 我错过了什么?如果有更好的方法来做到这一点,还有什么建议吗?

编辑 1:

感谢您的评论指出我在应该使用 char 的地方使用了 int。但更好的是 @kelalaka 指出 mpz_class 有一个内置函数,它让我有 2 个不同的选项

下面是 mpz_out_raw 的替代品,除了它需要一个 mpz_class 作为输入而不是 mpz_t op 假设您始终使用少于 256 个字节,则每个写入的数字可节省 3 个字节,但速度要慢 5 倍。

void nonStandard(FILE *stream, mpz_class op) {
    unsigned char length=0;
    unsigned char bytes[127];
    while (op>0) {
        mpz_class t=op%256;
        bytes[length+1]=t.get_ui();
        op/=256;
        length++;
    }
    unsigned char buffer[length+1];
    buffer[0]=length;
    for (char i=length-1;i>=0;i--) buffer[length-i]=bytes[i];
    fwrite(buffer, sizeof(unsigned char),length+1, stream);
}

I have a lot of 20 byte integers I want to write to disk. I have them stored in ram using the GMP mpz_class

I have tried using the following test code but in the file is 20x 0s not the expected 00000000 00000000 00000000 00000000 21F882C7

#include <iostream>
#include <fstream>
#include <string>
#include <gmpxx.h>
using namespace std;

int main() {
    mpz_class userId;
    userId="569934535";

    //open user file
    string fileName= "test.bin";
    ofstream mapFile(fileName,ios::binary);

    //save userId
    mpz_class temp=userId;  //copy so original not destroyed(never reused in example but in real life it would)
    unsigned int bytes[20];
    for (unsigned char i=0;i<20;i++) {
        mpz_class t=temp%256;
        bytes[19-i]=t.get_ui();
        temp/=256;
    }
    mapFile.write((char*)&bytes,20);//expecting to write 00000000 00000000 00000000 00000000 21F882C7
    mapFile.close();

    return 0;
}

I am new to c++ what am I missing? also any suggestions if there is a better way to do this?

Edit 1:

Thanks for comments for pointing out that I was using an int where I should have been using a char. But even better @kelalaka pointed out mpz_class had a built in function which got me to 2 different options

The below is a drop in replacement for mpz_out_raw excepts it takes a mpz_class as input instead of mpz_t op It saves 3 bytes per number written assuming you are always using less then 256 bytes but it is 5x slower.

void nonStandard(FILE *stream, mpz_class op) {
    unsigned char length=0;
    unsigned char bytes[127];
    while (op>0) {
        mpz_class t=op%256;
        bytes[length+1]=t.get_ui();
        op/=256;
        length++;
    }
    unsigned char buffer[length+1];
    buffer[0]=length;
    for (char i=length-1;i>=0;i--) buffer[length-i]=bytes[i];
    fwrite(buffer, sizeof(unsigned char),length+1, stream);
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

趁微风不噪 2025-01-18 20:48:20

事实证明 gmp 有一个将数字写入文件流 mpz_out_raw 的函数,但是它使用 4 字节长度值,这对我来说已经过时了,所以我编写了一个类似的函数,仅使用 1 字节长度价值。虽然我的函数保存了 3 个字节的存储数据,但运行时间比本机函数长 5 倍,因此可能不需要。

下面是我的函数 nonStandard 和一个测试其速度的示例脚本。它将向磁盘写入 1000000 个数字并记录所花费的时间。

#include <iostream>
#include <string>
#include <gmpxx.h>
using namespace std;

#include <chrono>
#include <thread>

using Clock = std::chrono::steady_clock;
using std::chrono::time_point;
using std::chrono::duration_cast;
using std::chrono::milliseconds;
using namespace std::literals::chrono_literals;
using std::this_thread::sleep_for;


/**
 * This function only works with numbers up to 2^1016
 * @param stream
 * @param op
 */
void nonStandard(FILE *stream, mpz_class op) {
    unsigned char length=0;
    unsigned char bytes[127];
    while (op>0) {
        mpz_class t=op%256;
        bytes[length]=t.get_ui();
        op/=256;
        length++;
    }
    unsigned char buffer[length+1];
    buffer[0]=length;
    for (char i=length-1;i>=0;i--) buffer[length-i]=bytes[i]; // NOLINT(cppcoreguidelines-narrowing-conversions)
    fwrite(buffer, sizeof(unsigned char),length+1, stream);
}

int main() {
    mpz_class userId;
    userId="345474756569934535";
    FILE* mapFile = fopen("mpz_out_raw.bin", "wb");



    time_point<Clock> start = Clock::now();
    //test start
    for (int i=0;i<1000000;i++) {
        userId+=7;
        mpz_out_raw(mapFile,userId.get_mpz_t());
    }
    fclose(mapFile);
    //test end
    time_point<Clock> end = Clock::now();
    milliseconds diff = duration_cast<milliseconds>(end - start);
    std::cout << "mpz_out_raw: " << diff.count() << "ms" << std::endl;



    userId="345474756569934535";
    mapFile = fopen("nonStandard.bin", "wb");
    start = Clock::now();
    //test start
    for (int i=0;i<1000000;i++) {
        userId+=7;
        nonStandard(mapFile,userId);
    }
    fclose(mapFile);
    //test end
    end = Clock::now();
    diff = duration_cast<milliseconds>(end - start);
    std::cout << "nonStandard: " << diff.count() << "ms" << std::endl;

    return 0;
}

Turns out gmp has a function for writing the number to a file streem mpz_out_raw however it uses a 4 byte length value which for my use is over kill so I wrote a similar function that only used a 1 byte length value. Though my function saves 3 bytes of storage data it takes 5 times longer to run then the native function so is probably not desired.

Below is my function nonStandard and an example script to test its speed. It will write 1000000 numbers to the disk and time how long it took.

#include <iostream>
#include <string>
#include <gmpxx.h>
using namespace std;

#include <chrono>
#include <thread>

using Clock = std::chrono::steady_clock;
using std::chrono::time_point;
using std::chrono::duration_cast;
using std::chrono::milliseconds;
using namespace std::literals::chrono_literals;
using std::this_thread::sleep_for;


/**
 * This function only works with numbers up to 2^1016
 * @param stream
 * @param op
 */
void nonStandard(FILE *stream, mpz_class op) {
    unsigned char length=0;
    unsigned char bytes[127];
    while (op>0) {
        mpz_class t=op%256;
        bytes[length]=t.get_ui();
        op/=256;
        length++;
    }
    unsigned char buffer[length+1];
    buffer[0]=length;
    for (char i=length-1;i>=0;i--) buffer[length-i]=bytes[i]; // NOLINT(cppcoreguidelines-narrowing-conversions)
    fwrite(buffer, sizeof(unsigned char),length+1, stream);
}

int main() {
    mpz_class userId;
    userId="345474756569934535";
    FILE* mapFile = fopen("mpz_out_raw.bin", "wb");



    time_point<Clock> start = Clock::now();
    //test start
    for (int i=0;i<1000000;i++) {
        userId+=7;
        mpz_out_raw(mapFile,userId.get_mpz_t());
    }
    fclose(mapFile);
    //test end
    time_point<Clock> end = Clock::now();
    milliseconds diff = duration_cast<milliseconds>(end - start);
    std::cout << "mpz_out_raw: " << diff.count() << "ms" << std::endl;



    userId="345474756569934535";
    mapFile = fopen("nonStandard.bin", "wb");
    start = Clock::now();
    //test start
    for (int i=0;i<1000000;i++) {
        userId+=7;
        nonStandard(mapFile,userId);
    }
    fclose(mapFile);
    //test end
    end = Clock::now();
    diff = duration_cast<milliseconds>(end - start);
    std::cout << "nonStandard: " << diff.count() << "ms" << std::endl;

    return 0;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文