user3184733
user3184733

Reputation: 65

How to stop MATLAB from rounding extremely small values to 0?

I have a code in MATLAB which works with very small numbers, for example, I have values that are on the order of 10^{-25}, however when MATLAB does the calculations, the values themselves are rounded to 0. Note, I am not referring to format to display these extra decimals, but rather the number itself is changed to 0. I think the reason is because MATLAB, by default, uses up to 15 digits after the decimal point for its calculations. How can I change this so that numbers that are very very small are retained as they are in the calculations?

EDIT:

My code is the following:

clc;
clear;

format long;

% Import data
P = xlsread('Data.xlsx', 'P');
d = xlsread('Data.xlsx', 'd');
CM = xlsread('Data.xlsx', 'Cov');


Original_PD = P;                       %Store original PD
LM_rows = size(P,1)+1;                           %Expected LM rows
LM_columns = size(P,2);                 %Expected LM columns
LM_FINAL = zeros(LM_rows,LM_columns);    %Dimensions of LM_FINAL

for ii = 1:size(P,2)

P = Original_PD(:,ii);
% c1, c2, ..., cn, c0, f
interval = cell(size(P,1)+2,1);

for i = 1:size(P,1)
    interval{i,1} = NaN(size(P,1),2);
    interval{i,1}(:,1) = -Inf;
    interval{i,1}(:,2) = d;

    interval{i,1}(i,1) = d(i,1);
    interval{i,1}(i,2) = Inf;
end
interval{i+1,1} = [-Inf*ones(size(P,1),1) d];
interval{i+2,1} = [d Inf*ones(size(P,1),1)];

c = NaN(size(interval,1),1);
for i = 1:size(c,1)
    c(i,1) = mvncdf(interval{i,1}(:,1),interval{i,1}(:,2),0,CM);
end

c0 = c(size(P,1)+1,1);
f = c(size(P,1)+2,1);
c = c(1:size(P,1),:);
b0 = exp(1);
b = exp(1)*P;

syms x;

eqn = f*x;
for i = 1:size(P,1)
    eqn = eqn*(c0/c(i,1)*x + (b(i,1)-b0)/c(i,1));
end

eqn = c0*x^(size(P,1)+1) + eqn - b0*x^size(P,1);

x0 = solve(eqn);
x0 = double(x0);

for i = 1:size(x0)
    id(i,1) = isreal(x0(i,1));
end

x0 = x0(id,:);
x0 = x0(x0 > 0,:);

clear x;

for i = 1:size(P,1)
    x(i,:) = (b(i,1) - b0)./(c(i,1)*x0) + c0/c(i,1);
end

% x = [x0 x1 ... xn]
x = [x0'; x];
x = x(:,sum(x <= 0,1) == 0);

% lamda
lamda = -log(x);
LM_FINAL(:,ii) = lamda;
end

The problem is in this step:

 for i = 1:size(P,1)
        x(i,:) = (b(i,1) - b0)./(c(i,1)*x0) + c0/c(i,1);
end

where the "difference" gets very close to 0. How can I stop this rounding from occurring at this step?

For example, when i = 10, I have the following values:

b_10 = 0.006639735483297
b_0 = 2.71828182845904
c_10 = 0.000190641848119641
c_0 = 0.356210110252579
x_0 = 7.61247930625269

After doing the calculations we get: -1868.47805854794 + 1868.47805854794 which yields a difference of -2.27373675443232E-12, that gets rounded to 0 by MATLAB.

EDIT 2:

Here is my data file which is used for the code. After you run the code (should take about a minute and half to finish running), row 11 in the variable x shows 0 (even after double clicking to check it's real value), when it shouldn't.

Upvotes: 1

Views: 5684

Answers (1)

Mark Mikofski
Mark Mikofski

Reputation: 20178

The problem you're having is because the IEEE standard for floating points can't distinguish your numbers from zero because they don't utilize sufficient bits.

Have a look at John D'Errico's Big Decimal Class and Variable Precision Integer Arithmetic. Another option would be to use the Big Integer Class from Java but that might be more challenging if you are unfamiliar with using Java and othe rexternal libraries in MATLAB.

Can you give an example of the calculations in which you are using 1e-25 and getting zero? Here's what I get for a floating point called small_num and one of John's high-precision-floats called small_hpf when assigning them and multiplying by pi.

>> small_num = 1e-25

small_num =

   1.0000e-25

>> small_hpf = hpf(1e-25)
small_hpf =
1.000000000000000038494869749191839081371989361591338301396127644e-25
>> small_num * pi

ans =

   3.1416e-25

>> small_hpf * pi
ans =
3.141592653589793236933163473501228686498684350685747717239459106e-25

Upvotes: 5

Related Questions