matlab代码中的基本转换错误

时间:2014-07-03 12:04:27

标签: math matlab

我创建了以下简单的matlab函数,将数字从任意基数转换为十进制并返回

这是第一个

function decNum = base2decimal(vec, base)

decNum = vec(1);
for d = 1:1:length(vec)-1
    decNum = decNum*base + vec(d+1);     
end 

这是另一个

function baseNum = decimal2base(num, base, Vlen)
ii = 1;
if num == 0
    baseNum = 0;
end
while num ~= 0 
    baseNum(ii) = mod(num, base);
    num = floor(num./base);
    ii = ii+1;
end
baseNum = fliplr(baseNum);

if Vlen>(length(baseNum))
    baseNum = [zeros(1,(Vlen)-(length(baseNum))) baseNum ];
end

由于这些功能有多大可以成功转换不同的大向量,但是在测试它们时我注意到以下错误

让我们使用以下测试功能

num = 201;

pCount = 7
x=base2decimal(repmat(num-1, 1, pCount), num)
repmat(num-1, 1, pCount)
y=decimal2base(x, num, 1)
isequal(repmat(num-1, 1, pCount),y) 

base201 七(7)位的假设矢量工作正常,但 base200 的相同矢量不会返回预期结果即使它更小,理论上应该成功转换。

2 个答案:

答案 0 :(得分:1)

(一个初步评论:呼叫base2decimal不会导致十进制数字,而是一个数字:-D)

这是由于浮点限制精度(在我们的例子中为double)。要测试它,只需在MATLAB命令窗口输入:

>> 200^7 - 1 == 200^7

ans = 

     1

>> mod(200^7 - 1, 200)

ans =

     0

这意味着您在基数200(正好是200 7 -1)中的数字值恰好表示为200 7 ,并且"真"表示值为200 7

另一方面:

>> 201^7 - 1 == 201^7

ans =

 1

所以这两个数字仍然表示相同,但​​

>> mod(201^7 - 1, 201)

ans =

   200

这意味着这两个值共享" true" 201 7 -1的表示,这是您预期的值。

<强> TL; DR

当存储在double中时,200 7 -1不准确地表示为200 7 ,而201 7 -1是准确的代表。

&#34;较大的数字表示不如较小的数字&#34;是一种误解:如果确实如此,就没有大数字可以完全代表。

答案 1 :(得分:0)

从你自己的观察来看:

  1. 在大多数情况下,代码可以正常工作
  2. 代码可以为大数字提供小错误
  3. 嫌疑人显而易见:

    舍入问题似乎给你带来了麻烦。 @RTL在评论中也说明了这一点。


    第一个问题现在应该是: 你需要这么大数字的完美准确度吗?或者,如果有时相对较小的数量是关闭的话还可以吗?

    如果回答是,我会建议您尝试不同的存储格式。 简单的解决方案是使用大整数:

    uint64
    

    另一种方法是制作自己的存储格式。如果你需要更大的数字,这是必需的。我认为你可以通过一个单元阵列和一些技巧来覆盖一个巨大的范围,但是当然很难将这些数字组合起来而不会失去你努力工作的准确性。