【问题标题】:Matlab: Loss of precision in calculations. Scaling of variables possible?Matlab:计算中的精度损失。可以缩放变量吗?
【发布时间】:2013-04-28 11:00:44
【问题描述】:

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

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

在哪里

一个=

                  346751.503002533 

g =

                  9.81

bB =

                  2000

标准 =

      749.158805838953
      848.621203222693
       282.57250570754
      1.69002068665559
      529.068503515487

你=

     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));

【问题讨论】:

  • 以这种方式使用vpa会首先以双精度计算括号内的值,因此使用vpa()将没有任何好处。请参阅 MATLAB 的帮助以获取解释,以及如何在 vpa 中使用符号数。尽管如此,差异是如此之小,以至于我宁愿担心@CST-link 所写的输入数据精度:)

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


【解决方案1】:

我运行了这个只使用你的向量的测试:

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) 你确定三个向量的元素乘积不应该返回一个统一值向量吗?

稍后编辑

我们只显示向量相关性并忽略标量,因为它们对所有向量分量的贡献相同。我们将使用“~”来表示向量分量之间的比例。然后,根据你的公式:

Ki ~ ui−2 × Sd i-2

Tpi ~ Ki-1/2 × ui-1 × Sdi-1

将第一个公式代入第二个公式,得到:

Tpi ~ (ui−2 × Sdi-2)-1/2 × ui-1 × Sdi-1

或者,经过一些简单的代数操作:

Tpi ~ ui(-2×-1/2) sup> × Sdi(−2×−1/2) × ui sub>-1 × Sdi-1

Tpi ~ ui × Sdi × ui-1 × Sdi- 1

Tpi ~ 1i

所以,是的,您的结果向量 Tp 应该 具有相同值的所有分量;这不是事故或精度限制的结果。这是因为您计算 KTp 或两者的方式。

【讨论】:

  • 由于我不是母语人士,能否请您重新表述一下您所说的 rigged 是什么意思?它们确实返回完全相同的值!公式中的 r 为 0.0143! max_r-min_r 不返回零的事实是否显示了 r DO 内的值发生变化的事实,或者这现在只是精度损失的情况,我们将数字相减吗?进一步解释我的问题:这些值是蒙特卡罗分析的摘录。 Sd 是 n 个正态分布值,u 和 K 使用 Sd 计算。那么我相信这些价值观吗?不!我只想运行脚本以查看 Tp 的最大变化
  • @TheodorBecker:“操纵”就像“特别设置”一样(也不是以英语为母语的人)。而且,因为其中一个因素是随机的,并不意味着结果是随机的。如果 a 是随机的,那么 b = 1 / a 也是随机的,但 ab 不再是随机的。这就是我问这个问题的原因。 2. 也许您发布了您使用的公式,我们看到了而不是猜测它。如果你不能这样做,那么我所能建议的就是将你的公式转换为以Sd 扩展的泰勒级数,并查看线性、二次等项与常数项相比的贡献。
  • @CST-Link:我在第一篇文章中添加了更多代码。也许这有助于澄清我的问题。也许我没有正确理解你的第二个问题。统一值向量是什么意思?我计算的大多数值,如 Qp、Al、bB 都是给定和设置的,有些我现在还不确定。因此,我想用均匀分布 (r,s) 来解决这个问题,分别计算 Rd、Sd,并对 Tp 随 r 和 s 的变化进行敏感性分析。
  • @TheodorBecker:我的帖子中的“统一值向量”的意思是“所有组件的值都相同的向量”(与随机变量的均匀分布无关。)我在看你的代码现在...如果我有相关的事情,请与 cmets 一起回来。
  • @TheodorBecker:您好,我已经编辑了我的评论以考虑您的新意见。显然这不是机器的错误或精度的限制。这些值应该是相等的。围绕“真实”值的波动,而是由于精度限制。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-19
  • 1970-01-01
  • 2019-02-03
  • 2018-11-26
  • 2014-06-24
  • 1970-01-01
相关资源
最近更新 更多