我想将一个八进制字符串转换为一个短的双精度数组。挑战是将两个以上的字符压缩为双精度值。一个字符很简单(只需使用字符的值并将其转换为双精度)。所以一个 'a' 可以转换为 '97.0' 。两个字符也可以很简单。'ab' 可以转换为 '97.98'。但是两个如何将三个字符转换为双精度?请考虑 matlab 中的舍入。
我想这样做的原因是所有数据都需要发送到另一个只接受双打的产品。
我想将一个八进制字符串转换为一个短的双精度数组。挑战是将两个以上的字符压缩为双精度值。一个字符很简单(只需使用字符的值并将其转换为双精度)。所以一个 'a' 可以转换为 '97.0' 。两个字符也可以很简单。'ab' 可以转换为 '97.98'。但是两个如何将三个字符转换为双精度?请考虑 matlab 中的舍入。
我想这样做的原因是所有数据都需要发送到另一个只接受双打的产品。
双精度使用 8 字节 = 64 位。
一个 ASCII 字符使用 1 个字节,但典型的 ASCII 编码只使用前 7 位。
因此,如果我们将自己限制为标准 ASCII 字符(在 1 - 127 范围内),我们应该能够将 9 个字符放入每个双精度字符中,因为 7*9=63<64。
(我们甚至还有 1 位可用,我们可以在每组 7 个双精度中加入另一个字符,但我将忽略优化。我们也忽略了任何关于 unicode 的讨论,但这适用于许多应用程序。 )
有几个 Matlab 命令需要注意:
typecast:在不修改底层位的情况下执行类型转换。我们将使用它从double
to/from转换uint64
。
bitshift:对整数数据类型执行位移。也可以使数据饱和,只保留最低的 N 位。
bitor:执行顾名思义.. 对无符号整数进行位级 OR 运算。
然后,经过一些实验,我们可以取一些字符串:
strIn = 'How much wood could a woodchuck chuck if a woodchuck could chuck wood?';
然后我们可以使用以下循环将其编码为asDouble
数组(通过):asUint64
%Convert into doubles. 9 characters per double, 7 bits each.
asUint64 = zeros(1,ceil(length(strIn)/9),'uint64');
for ixChar = 1:length(strIn);
ixUint64 = ceil(ixChar/9); %Which uint64 are we writing to?
ix7Group = mod(ixChar, 9); %Which 7-bit piece are we writing to?
%Create the encoded value
curChar = strIn(ixChar);
encoded = bitshift(uint64(curChar), ix7Group*7);
%OR it into the current uint64
asUint64(ixUint64) = bitor(asUint64(ixUint64), encoded);
end
asDouble = typecast(asUint64,'double');
我们可以使用非常相似的循环将其转换回来
%Convert back to str
strOut = char(zeros(1,length(asDouble)*9));
asUint64Out = typecast(asDouble,'uint64');
for ixChar = 1:length(strOut);
ixUint64 = ceil(ixChar/9); %Which uint64 are we reading from?
ix7Group = mod(ixChar, 9); %Which 7-bit piece are we reading from?
%Use bitshift to get only the desired bits
encodedOut = bitshift(asUint64Out(ixUint64), -ix7Group*7, 7);
%Cast to a char and store
strOut(ixChar) = char(encodedOut);
end
%Strip unset characters
strOut(strOut==0)=[];
对于它的价值,asDouble
数组如下,但此时以十进制考虑它是非常危险的:
>> asDouble'
5.56929305361178e+196
6.06383983172222e+259
8.04093567858749e+177
3.37314706618397e+259
2.82456187483837e+266
1.79945353109827e-150
3.3731457960492e+259
2.81037121975641e-306
由于二进制是一种更好的思考方式:
0110100011000111110101110110101000001110111110111110010000100000
0111010111011111100011010000011001001101111110111111101111101100
0110010011011111101111111011101000001100001010000011001001100011
0111010111010001100011010000011010111100011111010111010001100011
0111011101000001100001010000011001101101001010000011010111101111
0010000011010111100011111010111010001100011110010011011111100011
0111010111010001100011010000011001001101100111010111011111100011
0000000001111111100100110111111011111110111010000011010110000000