生成在 C 语言中具有可重现结果的半 RNG(非随机/随机)

问题描述 投票:0回答:1

我希望创建一个“随机性”,或者至少在给定某些数据集的情况下创建大量的熵。不过,基于各种因素、使用的数据集等,结果必须是可预测/恒定的。所以我不希望只从随机/随机中读取。我需要这个是完全可重现的。我只是希望使用相当有限的密钥大小在数据集中的分布足够多样化。我想一个大概的想法:

[键] --> [数据集A] --> [可再现数字系列]。由于对键和任何附加变量的微小修改,数字将发生显着变化。请注意,我试图避免只是散列,因为我的要求需要从仍会模拟随机性而不是随机性的数据集中查找。它是按程序生成的,但可重现。我希望它可以用 C 实现,因为我想将它用于(非学校)项目。这是一种爱好,但本质上我希望最终能够知道某些标准会产生非常不同的结果。一切都必须是独立的(没有外部依赖性,仅在代码和数据集以及密钥内)。

如果我从错误的角度看待这个问题,我愿意接受其他建议,但显然最好不要从头开始编写其余的代码库。

提前致谢,

  • 内特

我已经尝试了几种基于密钥大小和内容以及数据集内容的“虚构”“算法”。不过,我没有获得足够的熵。

c random dataset key predictive
1个回答
0
投票

好的,这是简单的线性同余生成器,用于 64 位 -> 64 位全周期映射,以及反函数。

#include <stdint.h>
#include <stdio.h>

// parameters from https://arxiv.org/pdf/2001.05304.pdf
uint64_t m = 0xd1342543de82ef95ULL;
uint64_t c = 0x1ULL;

uint64_t im = 6281218453581128637ULL; // modular inverse from m using Mathematica ModularInverse[m, 2^64]

uint64_t lcg(uint64_t xi) { // direct LCG
    return m*xi + c;
}

 uint64_t ilcg(uint64_t xp) { // inverse LCG, such that ilcq(lcg(q)) == q
    return (xp - c)*im;
}

int main() {
    
    uint64_t idx = 987610342345234534ULL;
    
    printf( "LCG is %llu\n", lcg(idx) );
    printf( "INV is %llu\n", ilcg(lcg(135797531ULL)) );

    return 0;
}

这是128位LCG

typedef union {
    uint8_t     c[16];
    __uint128_t ui;
} x128;

const x128 zm = { .c = {0xdb,0x36,0x35,0x77,0x34,0xe3,0x4a,0xbb,0x00,0x50,0xd0,0x76,0x1f,0xcd,0xfc,0x15} }; // parameters from https://arxiv.org/pdf/2001.05304.pdf
const x128 zc = { .c = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01} };

__uint128_t lcg(__uint128_t xi) {
    return zm.ui*xi + zc.ui;
}

void prn128(__uint128_t x) {
    printf("0x");
    for (int i = 0; i != 16; ++i) {
        printf("%02x", (int)((x >> 8*i)) & 0xff);
    }
    printf("\n");    
}

int main() {
    __uint128_t a = (__uint128_t)9129178291273918391ULL * 19284633241ULL * 3173197ULL;
    
    prn128(zm.ui);
    prn128(zc.ui);
    prn128(a);
    prn128(lcg(a));    

    return 0;
}
© www.soinside.com 2019 - 2024. All rights reserved.