在MATLAB中将数字转换为字符串

时间:2012-06-05 20:04:57

标签: string matlab floating-point number-formatting

假设我想将数字0.011124325465476454转换为MATLAB中的字符串。

如果我点击

mat2str(0.011124325465476454,100)

我得到的0.011124325465476453在最后一位数上有所不同。

如果我点击num2str(0.011124325465476454,'%5.25f')

我得到0.0111243254654764530000000

用不合适的零填充,最后一位数字不同(3应为4)。

我需要一种方法将带有随机小数位数的数字转换为它们的EXACT字符串匹配(没有填充零,没有最后的数字修改)。

有这样的方法吗?

编辑:由于我不记得Amro和nrz提供的关于精度的信息,我正在添加一些关于该问题的更多信息。我实际需要转换的数字来自一个C ++程序,它将它们输出到一个txt文件,它们都是C ++ double类型。 [注意:从txt文件输入数字到MATLAB的部分不是由我编码的,我实际上不允许修改它以将数字保持为字符串而不将它们转换为数字。我只能访问此代码的“输出”,这是我想要转换的数字]。到目前为止,我还没有得到超过17位小数的​​数字(注意:因此上面提供的例子,18位小数,并不是很有说服力)。

现在,如果数字有15位数,例如0.280783055069002

然后num2str(0.280783055069002,'%5.17f')mat2str(0.280783055069002,17)返回

0.28078305506900197

这不是确切的数字(见最后的数字)。

但如果我点击mat2str(0.280783055069002,15)我就会

0.280783055069002这是正确的!!!

可能有一百万种方法来“编码”问题(例如创建一个执行转换的例程),但是当我输入一个数字时,使用标准的内置MATLAB来获得期望的结果是不是有某种方法随机小数位数(但不超过17);

4 个答案:

答案 0 :(得分:4)

我的HPF工具箱还允许您在MATLAB中使用任意精度的数字。

在MATLAB中,试试这个:

>> format long g
>> x = 0.280783054
x =
               0.280783054

正如您所看到的,MATLAB使用您提供的数字将其写出来。但MATLAB如何真正“感受”这个数字呢?它在内部存储什么?看看sprintf说的是什么:

>> sprintf('%.60f',x)
ans =
0.280783053999999976380053112734458409249782562255859375000000

这就是HPF在尝试从双倍中提取该数字时所看到的:

>> hpf(x,60)
ans =
0.280783053999999976380053112734458409249782562255859375000000

事实是,几乎所有的十进制数都不能用浮点运算作为双精度表示。 (由于显而易见的原因,0.5或0.375是该规则的例外。)

但是,当以18位数的十进制形式存储时,我们发现HPF不需要将该数字存储为十进制形式的二进制近似值。

x = hpf('0.280783054',[18 0])
x =
0.280783054

>> x.mantissa
ans =
  2 8 0 7 8 3 0 5 4 0 0 0 0 0 0 0 0 0

niels不理解的是十进制数不是以十进制形式存储为double。例如,0.1内部看起来像什么?

>> sprintf('%.60f',0.1)
ans =
0.100000000000000005551115123125782702118158340454101562500000

如您所见,matlab不会将其存储为0.1。事实上,matlab存储0.1作为二进制数,这里实际上是......

1/16 + 1/32 + 1/256 + 1/512 + 1/4096 + 1/8192 + 1/65536 + ...

或者如果您愿意

2^-4 + 2^-5 + 2^-8 + 2^-9 + 2^-12 + 2^13 + 2^-16 + ...

为了准确地表示0.1,这将花费无数多个这样的项,因为0.1是二进制的重复数。 MATLAB停止在52位。就像2/3 = 0.6666666666 ...作为小数,0.1仅作为双重近似存储。

这就是为什么你的问题完全是关于精度和双重包含的二进制形式的原因。

作为聊天后的最终编辑......

关键是MATLAB使用double来表示数字。因此,它将采用最多15个十进制数字的数字,并能够使用正确的格式设置将它们喷出。

>> format long g
>> eps 
ans = 
2.22044604925031e-16

所以例如......

>> x = 1.23456789012345
x =
          1.23456789012345

我们看到MATLAB已经做对了。但现在再添加一个数字。

>> x = 1.234567890123456
x =
          1.23456789012346

完全荣耀,看看x,就像MATLAB看到的那样:

>> sprintf('%.60f',x)
ans =
1.234567890123456024298320699017494916915893554687500000000000

所以请始终注意任何浮点数的最后一位数。 MATLAB将尝试智能地对事物进行处理,但15位数字就在您安全的边缘。

是否有必要使用HP​​F或MP等工具来解决此类问题?不,只要你认识到双重的限制。但是,提供任意精度的工具使您能够在需要时更灵活。例如,HPF在该地下室区域中提供保护数字的使用和控制。如果您需要它们,它们可以保存您从腐败中获得的数字。

答案 1 :(得分:0)

您可以将Multiple Precision Toolkit from MATLAB File Exchange用于任意精确数字。浮点数通常不具有精确的基数10表示。

答案 2 :(得分:0)

那是因为你的数字超出了double数字类型的精度(它给你15到17个有效十进制数字)。在您的情况下,一旦评估了文字,它就会四舍五入到最接近的可表示数字。

如果您需要比双精度浮点提供的精度更高的精度,请将数字存储在字符串中,或​​使用任意精度库。例如,使用符号工具箱:

sym('0.0111243254654764549999999')

答案 3 :(得分:0)

您无法获取EXACT字符串,因为该数字存储为double类型,甚至是long double类型。 存储的数字将比您给出的数字更精细或更少。

计算机只知道二进制数0&你必须知道一个基数中的数字在其他基数中可能不相同。例如,数字1/3,基数10得到0.33333333 ...(省略号(三个点)表示仍有更多的数字,这里是数字3),它将被截断为0.333333;基数3产生0.10000000,看,不多或少,确切的数量;基数2产生0.01010101 ...,因此在计算机中它可能被截断为0.01010101,即85/256,小于1/3的舍入,下次取数字时,它将不一样你想

所以从一开始,你应该将数字存储在字符串而不是浮点类型中,否则会失去精度。

考虑到精度问题,MATLAB提供了任意精度的符号计算。