问题 1:我有一个有理数的十进制表示。
太好了。到目前为止一切顺利...
这是生成二进制数的代码。
不,这是生成数字的二进制表示的代码。它与您以十进制表示的数字相同。我知道你认为我很迂腐,但据我所知,这是你困惑的根源。数字是一个数字,与表示无关。五只羊就是五只羊,无论你是用二进制、十进制、八进制还是用 Hammish 左手的手指写(他只剩下 4 个)。
让我们稍微修改一下你的代码。
bits = 32;
r = rand();
[num, den] = rat(r);
q = 2^bits;
x(1) = num / den;
x(1) 中存储的值是一个有理数。如果我们在 Matlab 中输入disp(x(1)),它将以十进制表示显示该数字的值。我们可以使用dec2bin 命令将该表示更改为二进制:
b(1,:) = dec2bin(round(x(1)*q), bits);
但它仍然是相同的数字。 (实际上,它不是同一个数字,因为我们现在将精度限制为 bits 位,而不是 Matlab 生成的原生 53 位。稍后会详细介绍。)
但是dec2bin 返回的值是字符串而不是数字。如果我们想实现您的功能并保持使用二进制表示的这种方式,我们可以这样做:
b(1,:) = dec2bin(round(x(1)*q), bits);
for d = 2:bits
b(d,:) = [b(d-1,2:end) '0'];
end
二进制表示的每次左移都会将该值乘以 2。通过忽略现在位于二进制点左侧的位,我隐式执行了 mod 操作。由于我们没有额外的有效数字要添加到值的最低有效位,所以我只添加一个零。
这会起作用;你会得到正确的值,并且可以对它们执行任何你想要的操作。您可以将它们表示为二进制或十进制,也可以将它们转换回分数,等等。
但是您可以在不转换为二进制表示的情况下实现相同的目标。
x(1) = num / den;
for d = 2:bits
x(d) = mod(x(d-1)*2, 1);
end
(请注意,我将 x(1) 中的值保留为分数。)
这对完全相同的数字执行完全相同的操作。一个区别是我一开始没有降低数字的精度,所以它使用完整的double 精度。现在,如果我想获取这些值并将它们表示为二进制,我仍然可以这样做(但请记住先将值强制为整数范围)。
c = dec2bin(round(x*q), bits);
这是两个版本的测试运行结果:
b =
11110000011101110111110010010001
11100000111011101111100100100010
11000001110111011111001001000100
10000011101110111110010010001000
00000111011101111100100100010000
00001110111011111001001000100000
00011101110111110010010001000000
00111011101111100100100010000000
01110111011111001001000100000000
11101110111110010010001000000000
11011101111100100100010000000000
10111011111001001000100000000000
01110111110010010001000000000000
11101111100100100010000000000000
11011111001001000100000000000000
10111110010010001000000000000000
01111100100100010000000000000000
11111001001000100000000000000000
11110010010001000000000000000000
11100100100010000000000000000000
11001001000100000000000000000000
10010010001000000000000000000000
00100100010000000000000000000000
01001000100000000000000000000000
10010001000000000000000000000000
00100010000000000000000000000000
01000100000000000000000000000000
10001000000000000000000000000000
00010000000000000000000000000000
00100000000000000000000000000000
01000000000000000000000000000000
10000000000000000000000000000000
c =
11110000011101110111110010010001
11100000111011101111100100100001
11000001110111011111001001000010
10000011101110111110010010000101
00000111011101111100100100001001
00001110111011111001001000010011
00011101110111110010010000100101
00111011101111100100100001001010
01110111011111001001000010010100
11101110111110010010000100101000
11011101111100100100001001010001
10111011111001001000010010100001
01110111110010010000100101000011
11101111100100100001001010000101
11011111001001000010010100001010
10111110010010000100101000010101
01111100100100001001010000101010
11111001001000010010100001010100
11110010010000100101000010100111
11100100100001001010000101001111
11001001000010010100001010011101
10010010000100101000010100111010
00100100001001010000101001110100
01001000010010100001010011101000
10010000100101000010100111010000
00100001001010000101001110100000
01000010010100001010011101000000
10000100101000010100111010000000
00001001010000101001110100000000
00010010100001010011101000000000
00100101000010100111010000000000
01001010000101001110100000000000
两者是相同的,除了 b 在 32 位后精度不足,c 有 53 位精度。您可以通过运行上面的代码来确认这一点,但将 x(1) 转换为 single:
x(1) = single(num / den);