Matlab:计算精度损失。变量的缩放可能吗?

时间:2013-04-28 11:00:45

标签: matlab floating-point-precision double-precision arbitrary-precision

今天我在Matlab中遇到了一个精确的问题:

Tp = a./(3600*sqrt(g)*sqrt(K).*u.*Sd*sqrt(bB))

,其中

a =

                  346751.503002533 

g =

                  9.81

bB =

                  2000

Sd =

      749.158805838953
      848.621203222693
       282.57250570754
      1.69002068665559
      529.068503515487

u =

     0.308500000000039
     0.291030000000031
      0.38996000000005
      0.99272999999926
     0.271120000000031

K =

 3.80976148470781e-009
 3.33620420353532e-009
 1.67593037457502e-008
 7.22952172629158e-005
 9.89028880679124e-009

显然,由于计算了不同维度的变量,我遇到了计算机精度问题:

Tp =

      48.2045906674902
      48.2045906674902
      48.2045906674902
      48.2045906674902
      48.2045906674902

不幸的是,我真的不知道如何处理这个问题。我玩输出格式,但这不是问题。所以我认为它确实是我的内部计算精度。 但是,如果我自己计算sqrt(K)。* u或u。* Sd,我会得到合理的值。只有当我将所有3个矩阵相乘时,我才会得到相同的值,尽管它应该有所不同。 我找到了这个帖子,但我的情况略有不同,因为我没有获得任意值,但由于某些原因它们都是相同的: numerical issue when computing complementary projection

我还认为缩放所有变量是这样的:Sd = Sd / max(Sd)可能会有所帮助,但由于我需要一个非常精确且尺寸正确的结果,这无济于事。

即使使用

vpa(a./(3600*sqrt(g)*sqrt(K).*u.*Sd*sqrt(bB)))

我每次都获得相同的值,但数字更多。这是为什么?

我希望你能帮助我。 干杯

编辑: 以下是更好地掌握我的问题的代码:

Al = 2835000000; % [m^2]
Qp = 3000000; [m^3*s^-1]
% draw 100 uniformally distributed values for s & r
s = 600 + (8000-600).*rand(100,1);
r = 600 + (15000-600).*rand(100,1);

% calculate Sd & Rd
Sd = 680./s;
Rd = 680./r;
figure
subplot(2,1,1)
hist(Sd)
subplot(2,1,2)
hist(Rd)

%% calculate my numerically
% calculate sigma
sig = Sd./Rd;

% define starting parameters for numerical solution
t = -1*ones(size(sig));
u = zeros(size(sig));
f = zeros(size(sig));

% define step
st = 0.00001;

% define break criterion
br = -0.001;

% increase u incrementally by st until t <= br
for i=1:length(sig)
    while t(i)<br
        while t(i)<-0.1
            f(i) = sig(i)*u(i)/sqrt(pi); % calculate f for convenience
            ierfc = exp(-f(i)*f(i))/sqrt(pi) - f(i)*erfc(f(i)); % calculate integral  of complementary error function
            t(i) = (u(i)/sqrt(pi))*erfc(-f(i))*(1+sig(i))-ierfc
            u(i) = u(i) + st*1000
        end
        while t(i)>=-0.1&& t(i)<br
            f(i) = sig(i)*u(i)/sqrt(pi); % calculate f for convenience
            ierfc = exp(-f(i)*f(i))/sqrt(pi) - f(i)*erfc(f(i)); % calculate integral of complementary error function
            t(i) = (u(i)/sqrt(pi))*erfc(-f(i))*(1+sig(i))-ierfc
            u(i) = u(i) + st;
        end
    end
end
figure
hist(u)


%% calculate K from Qp
K = 3/2*pi*(Qp^(2/3)*bB^(1/3))./(g^(1/3)*u.^2.*Sd.^2*Al);

%% calculate Tp
% in hours!
Tp = (3/2*sqrt(6*pi)*sqrt(Al))./(3600*sqrt(g)*sqrt(K).*u.*Sd*sqrt(bB));

1 个答案:

答案 0 :(得分:3)

我运行的测试只使用了矢量:

Sd = [                    ...
        749.158805838953  ...
        848.621203222693  ...
        282.57250570754   ...
        1.69002068665559  ...
        529.068503515487
];

u = [                     ...
        0.308500000000039 ...
        0.291030000000031 ...
        0.38996000000005  ...
        0.99272999999926  ...
        0.271120000000031 ...
];

K = [                         ...
        3.80976148470781e-009 ...
        3.33620420353532e-009 ...
        1.67593037457502e-008 ...
        7.22952172629158e-005 ...
        9.89028880679124e-009 ...
];

r = sqrt(K).*u.*Sd;
min_r = min(r);
max_r = max(r);
disp(min_r);
disp(max_r - min_r);

我得到了这个结果:

0.0143

3.2960e-17

对我来说,这似乎没有真正的精确度损失,但是你的矢量被操纵,它们将返回大致相同的值。我的意思是,当该值为10 ^ -2的数量级时,数量级10 ^ -17的误差相当小,接近双精度(16位十进制数字)的表示精度。并且,与转换为/来自十进制表示的精度损失相比,双浮点精度损失应该远远不是问题。所以问题是:1)您的数据源是否可靠和/或精确? 2)你确定三个向量的元素乘积不应该返回一个均匀值向量吗?

<强> LaterEdit

我们只显示向量依赖关系并忽略标量,因为它们通过相同的因子对所有向量组件做出贡献。我们将使用'〜'来表示矢量分量之间的比例。然后,根据你的公式:

K i u i -2 × Sd <子> I -2

Tp i K i -1/2 × u i -1 × Sd i -1 < / p>

通过将第一个公式插入第二个公式,可以得到:

Tp i 〜( u i -2 × Sd i -2 -1/2 × u i -1 × Sd i -1

或者,经过一些微不足道的代数操作:

Tp i u i ( - 2×-1 / 2)× i ( - 2×-1 / 2)× u i -1 × Sd i -1

Tp i u i × Sd i < / sub>× u i -1 × Sd i - 1

Tp i ~1 i

所以,是的,你得到的矢量 Tp 假设让所有组件具有相同的值;这不是事故或精度限制的结果。这是因为您计算 K Tp 或两者的方式。