【问题标题】:Convert decimal number to vector将十进制数转换为向量
【发布时间】:2012-01-11 17:26:04
【问题描述】:

在 matlab 中我想转换这个:

12345.6788993442355456789

变成一个向量

[1 2 3 4 5 6 7 8 8 9 9 3 4 4 2 3 5 5 4 5 6 7 8 9]

我已经找到了几种解决方案,可以使用 scanf, num2str,... 之类的命令将整数转换为向量,但这些解决方案不适合非整数,并且一些解决方案对于带有大量小数位的数字存在问题...

需要这种转换,因为我想查看和使用数字的所有数字。

【问题讨论】:

  • 我会把数字当作字符串,删除所有.s,然后使用你说的代码。
  • @Virginia:如果您的意思是在计算中需要使用所有数字,那么不用担心,即使默认情况下不会显示它们,Matlab 也会使用它们(尽管format long改变这个)。
  • @Jonas:不,她的示例号码中有太多数字“适合”double;一些在转换后立即丢失。
  • @AndrewJanke:你是对的。这确实是太多的数字。 +1 为您的解决方案,顺便说一句。

标签: matlab vector numbers digits decimal-point


【解决方案1】:

不熟悉 Matlab 语法,但如果你

  • 将数字转换为字符串
  • 循环遍历每个字符,如果字符不是小数点,则将数字添加到向量中

那会奏效的。可能有更有效的方法来做到这一点。

【讨论】:

  • 我已经尝试过,但是将数字转换为字符串仅适用于固定位数。
  • 你现在如何存储长十进制数?
【解决方案2】:

同样使用num2str,你可以这样做:

sol=arrayfun(@str2num,(sprintf('%f',23432.23432)),'UniformOutput',0)
horzcat(sol{:})

ans =

     2     3     4     3     2     2     3     4     3

您要保留有关逗号在哪里的信息吗?

【讨论】:

  • 谢谢!!...是的,我还需要逗号在哪里。
  • ...但是num2str的问题是它只能转换固定的位数,举个例子:
  • 如果我要号码23432.23432345678911111111111100998,你写的函数不起作用
  • 不幸的是,这些数字以 64 位双精度形式存储,因此存在最大精度。我对其进行了编辑以使其更精确。
  • 我的意思是:只要你写了 23432.23432345678911111111111100998,matlab 就将它转换成一个精度较低的数字(即双精度,64 位)
【解决方案3】:

您从哪个输入源获取这些数字?所有这些数字都很重要吗?您的示例数字已经超出了 double 数字类型的相对精度。 eps 函数会告诉你得到了多少舍入。

>> sprintf('%.20f', 12345.6788993442355456789)
ans =
12345.67889934423500000000
>> eps(12345.6788993442355456789)
ans =
    1.818989403545857e-012
>> sprintf('%.20f', 23432.23432345678911111111111100998)
ans =
23432.23432345678900000000
>> eps(23432.23432345678911111111111100998)
ans =
    3.637978807091713e-012

当您在 Matlab 源代码中键入一个数字时,它被视为 double 类型的文字。许多数字一输入就丢失了。有关更多讨论,请参阅此问题:In MATLAB, are variables REALLY double-precision by default?

如果您真的想保留所有这些数字,则首先需要避免将它们存储在双精度数中。从字符串中的完整数字开始,然后解析它。

function out = parseLongDecimal(str)
ixDot = find(str == '.');
if isempty(ixDot)
    out.whole = arrayfun(@str2double, str);
    out.fraction = [];
else
    out.whole = arrayfun(@str2double, str(1:ixDot-1));
    out.fraction = arrayfun(@str2double, str(ixDot+1:end));
end

这将保留所有数字。

>> xAsStr = '23432.23432345678911111111111100998';  % as a string literal, not numeric
>> parseLongDecimal(xAsStr)
ans = 
       whole: [2 3 4 3 2]
    fraction: [2 3 4 3 2 3 4 5 6 7 8 9 1 1 1 1 1 1 1 1 1 1 1 1 0 0 9 9 8]

根据您的用例,您也可以将其放入 Java BigDecimal 对象中并在那里使用它。

>> jx = java.math.BigDecimal(xAsStr)
jx =
23432.23432345678911111111111100998

【讨论】:

  • 这些数字来自之前的计算(这给了我非常相似的数字,所以我需要关注小数点后的数字)。谢谢你的回答
  • 之前的计算是用double 值完成的吗?如果是这样,由于精度问题,小数点后约 12 位以外的数字已经是虚假的,尝试保留它们是没有意义的。还是使用一些精度更高的类型并将它们作为字符串或其他东西返回?
  • 它返回双精度值。如何使用精度更高的类型?
  • 我有点困惑。为什么如果我将通过先前计算获得的双数乘以 10^5 等等(进行一种移位)我得到不同于零的数字?
猜你喜欢
  • 2011-08-10
  • 2017-01-31
  • 2015-11-12
  • 1970-01-01
  • 2015-01-26
  • 1970-01-01
  • 2013-05-31
  • 2018-07-04
相关资源
最近更新 更多