如何无损地将双精度数转换为字符串并返回八度

时间:2018-12-08 14:22:57

标签: octave

将双精度型保存到字符串时,会损失一些精度。即使您使用大量数字,转换也可能不可逆,即,如果将双x转换为字符串sx,然后再转换回数字,您将得到一个数字x'可能不等于x。例如,当检查一组测试中的差异时,这可能会引起一些问题。一种可能性是使用二进制形式(例如本机二进制形式或HDF5),但我想将数字存储在文本文件中,因此我需要转换为字符串。我有一个可行的解决方案,但请问是否有针对此或更佳解决方案的标准。

在C / C ++中,您可以将双精度转换为某个整数类型,例如char*,然后使用printf("%02x",c[j])将每个字节转换为长度为2的六进制。然后,例如PI将被转换为长度为16的字符串:54442d18400921fb。这样做的问题是,如果您阅读十六进制,您将不会知道它是哪个数字。因此,我对诸如pi-> 3.14{54442d18400921fb}之类的一些混合感兴趣。第一部分是数字的(可能是低精度)十进制表示形式(通常我会使用"%g"输出转换),大括号中的字符串是无损十六进制表示形式。

编辑:我将代码作为请求者传递

1 个答案:

答案 0 :(得分:1)

按照帖子中已经提出的想法,我写了 以下功能似乎有效。

function s = dbl2str(d);
  z = typecast(d,"uint32");
  s = sprintf("%.3g{%08x%08x}\n",d,z);
endfunction

function d = str2dbl(s);

  k1 = index(s,"{");
  k2 = index(s,"}");
  ## Check that there is a balanced {} or not at all                                      
  assert((k1==0) == (k2==0));

  if k1>0; assert(k2>k1); endif
  if (k1==0);
     ## If there is not {hexa} part convert with loss
     d = str2double(s); 
  else  
    ## Convert lossless
    ss = substr(s,k1+1,k2-k1-1);
    z = uint32(sscanf(ss,"%8x",2));
    d = typecast(z,"double");
  endif 
endfunction

那我有

>> spi=dbl2str(pi)
spi = 3.14{54442d18400921fb}

>> pi2 = str2dbl(spi)
pi2 =  3.1416
>> pi2-pi
ans = 0
>> snan = dbl2str(NaN)
snan = NaN{000000007ff80000}

>> nan1 = str2dbl(snan)
nan1 =  NaN

进一步的改进是使用其他类型的环境 实例Base64(由@CrisLuengo在评论中建议) 将二进制部分的长度从16个字节减少到11个字节。