当前位置: 首页 > 知识库问答 >
问题:

将随机字节转换为。净十进制0。。1分数范围

唐昊焜
2023-03-14

我正在玩一个TRNG usb设备,并成功地将随机字节转换为C#中的各种可用数据。

我想创建一个。0到0之间的净十进制值。。1(例如:0.37327)直接从使用二进制读取器的字节(或其他直接字节-

//假设:字节[]random_data适当的长度,图案为0...1范围十进制值=新的BinaryReader(新MemoryStream(random_data))。ReadDecimal();

我在寻找十进制的字节格式,但它看起来可能不是标准格式?

  • 如何将字节值转换为小数
  • 。NET十进制跨平台标准

这是业余工作,所以我可以接受使用将来可能会改变的东西。我已经查看了为示例输入十进制值生成的字节-我看到了负数和精度标志(最后一个int32中的1Ch max?),但编译器常量中的最小/最大数据值让我有点困惑,我正在生成大于零的值或无效值:

  • 最接近1(.99…9)的分数值:FFFFFF 0F 6102253E 5ECE4F20 00001C000
  • 最接近0(.00…1)的分数值:0100000000000000 00000000 00001C00

你能帮我找到生成完整分数0的正确路径吗。。1范围?

用“最终”代码编辑,感谢大家!

下面是我最后使用的C代码,它从一个合适的随机字节流(如TRNG设备、www.random.org或CSPRNG算法)创建一个范围为[0..1]的无偏随机十进制。生成的值看起来很好,边界测试通过,只要我避免了排版和复制/粘贴错误,这应该是可用的。

感谢您的帮助和有趣的讨论!

private decimal RandomDecimalRange01()
{
    // 96 bits of random data; we'll use 94 bits to directly map decimal's max precision 0..1 range
    byte[] data = new byte[12];
    decimal value = 0;

    // loop until valid value is generated, discarding invalids values. Mostly controlled by top 2 bits: 11 is always invalid, 00 or 01, is always valid, 10 has valid and invalid ranges. Odds make loop generally find value in one or a few iterations.
    while (true)
    {
        // Acquire random bytes from random source (like TRNG device or CSPRNG api)
        if (!trng.GetBytes(data))
        {
            throw new Exception("Failed to aquire random bytes from source");
        }
        else
        {
            // Read 94 random bits (pull 96 bits, discard 2)
            BinaryReader reader = new BinaryReader(new MemoryStream(data));
            int low = reader.ReadInt32();
            int mid = reader.ReadInt32();
            int high = reader.ReadInt32() & 0x3FFFFFFF; // don't consume upper 2 random bits - out of range

            // Discard invalid values and reloop (interpret special invalid value as 1)
            if (high > 542101086)
            {
                continue;
            }
            else if (high == 542101086)
            {
                if (mid > 1042612833)
                {
                    continue;
                }
                else if (mid == 1042612833)
                {
                    if (low > 268435455)
                    {
                        // Special override to generate 1 value for inclusive [0..1] range - interpret the smallest invalid value as 1. Remove code for exclusive range [0..1)
                        if (low == 268435456)
                        {
                            value = 1m; // return 1.0
                            break;
                        }
                        continue;
                    }
                }
            }

            // return random decimal created from parts - positive, maximum precision 28 (1C) scale
            value = new decimal(low, mid, high, false, 28);
            break;
        }
    }
    return value;
}

通过算法运行TrueRNGPro TRNG设备字节的示例生成值

0.8086691474438979082567747041
0.4268035919422123276460607186
0.7758625805098585303332549015
0.0701321080502462116399370731
0.3127190777525873850928167447
0.6022236739048965325585049764
0.1244605652187291191393036867

围绕有趣的边界值进行测试

// test databyte values for max & min ranges
new byte[] { 0x01, 0x00, 0x00, 0x10, 0x61, 0x02, 0x25, 0x3E, 0x5E, 0xCE, 0x4F, 0x20 }; // boundary: 1 too large for algorithm, will be discarded
new byte[] { 0x00, 0x00, 0x00, 0x10, 0x61, 0x02, 0x25, 0x3E, 0x5E, 0xCE, 0x4F, 0x20 }; // boundary: special 1 more than largest valid .99999..., interpret as 1 value
new byte[] { 0xFF, 0xFF, 0xFF, 0x0F, 0x61, 0x02, 0x25, 0x3E, 0x5E, 0xCE, 0x4F, 0x20 }; // boundary: largest valid value .9999...
new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // boundary: smallest valid value, should be 0
new byte[] { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // boundary: 1 more than smallest valid value, should be .000...1

共有2个答案

宓毅庵
2023-03-14
  • 是否要在0和1(包括两端)之间均匀分布

若你们使用十进制,我认为你们不会得到统一的分布,因为你们不能使用所有字节的整个范围。

对于浮点数,我认为如果你创建一个介于1和2之间的数字,然后减去1,可能更容易进行位操作。但是,您永远不会得到精确的1.0。

罗允晨
2023-03-14

从https://msdn.microsoft.com/en-us/library/system.decimal.getbits(v=vs.110). aspx

十进制数的二进制表示法由1位符号、96位整数和用于分割整数并指定其小数部分的比例因子组成。比例因子隐式为数字10,其指数范围为0到28。

返回值是一个由32位有符号整数组成的四元素数组。

返回数组的第一、第二和第三个元素包含96位整数的低、中、高32位。

返回数组的第四个元素包含比例因子和符号。它由以下部分组成:

位0到15,较低的字,是未使用的,必须是零。

位16到23必须包含一个介于0和28之间的指数,表示10除以整数的幂。

位24到30是未使用的,必须为零。

位31包含符号:0表示正,而1表示负。

您正在寻找0

乘以通过,这与0相同

这将枚举每个可能的96位整数和指数对,它们将产生0和1之间的decimal值(假设符号位设置为0)。

for (int exponent=0; exponent<=28; exponent++) {
    BigInteger max = BigInteger.Pow(10, exponent);
    for (int i = 0; i <= max; i++) {
        var fmt = "96bitinteger: {0}, exponent: {1}";
        Console.WriteLine(String.Format(fmt, i, exponent));
    }
}

1028十六进制为204fce5e 3e250261 10000000。因此,一旦你根据文档放置32位数字,然后出于某种原因创建最终32位,当他们说位0是指最高阶位时,从字节中构造十进制数字1并不难。

int[] data = new int[] { 0x10000000, 0x3e250261, 0x204fce5e, 0x1C0000 };
var random_data = data.SelectMany(BitConverter.GetBytes).ToArray();
decimal value = new BinaryReader(new MemoryStream(random_data)).ReadDecimal();
Console.WriteLine(value);

考虑更一般的<代码>新INT[] {a,b,c,0x1cOn}} /COD>。b和c上的约束,用于创建十进制数0

if c < 0x204fce5e:
    a can be anything
    b can be anything
elif c = 0x204fce5e:
    if b < 0x3e250261:
        a can be anything
    elif b = 0x3e250261
        constrain a <= 10000000
    b can not be greater than 0x3e250261
c can not be greater than 0x204fce5e.
 类似资料:
  • 将可变长度十六进制字符串(例如,转换为包含该数据的字节数组的最佳方式是什么。 即转换: 进入这个 还是这个 因此,当我将此写入一个文件并将其写入hexresp-C时,我将得到包含的二进制数据。

  • 本文向大家介绍Java将字节转换为十六进制代码分享,包括了Java将字节转换为十六进制代码分享的使用技巧和注意事项,需要的朋友参考一下 本文部分代码摘录自网上,并稍加整理,用于字节与十六进制之间的转换。

  • 问题内容: 我想知道如何在Python中将小数转换为最低形式的分数。 例如: 问题答案: 您有两种选择: 用途: (1, 4) (从Python 3.6开始,您可以对对象执行相同的操作。) 使用类型: Fraction(0.25) Fraction(1, 4) 后者具有非常有用的转换: 由于浮点值可能不精确,因此您可能会得到“奇怪”的分数;限制分母以某种程度“简化”分数,方法是: 如果您仍在使用P

  • 问题内容: 我写了一些代码将十六进制显示字符串转换为十进制整数。但是,当输入类似100a或625b(带有字母的东西)时,我得到了这样的错误: java.lang.NumberFormatException:对于输入字符串:java.lang.Integer.parseInt(未知源)处的java.lang.NumberFormatException.forInputString(未知源)处为“ 1

  • 我正在写一个Rust程序,读取I2C总线并保存数据。当我读取I2C总线时,我会得到十六进制值,比如,,等等。 现在,我只能将其作为字符串处理并按原样保存。有没有办法把它解析成一个整数?它有内置的功能吗?

  • 问题内容: 我有一个字节数组。我希望将该数组的每个字节String转换为其对应的十六进制值。 Java中是否有任何函数可以将字节数组转换为十六进制? 问题答案: 也可以看看 java.util.Formatter syntax %[flags][width]conversion Flag ‘0’ - The result will be zero-padded Width 2 Conversion