Count the number of sequential fractional *nines* of a decimal number

Dear all,
Does anyone know how to create a function that takes as input an array A and produces a second array with the number of sequential fractional nines for each element of array A?
For example I have an Array with the following numbers A = [0.999989023, 0.999994839, 0.999999751]
and want a function that calculates the following
B = [4, 5, 6] % A(1) has 4 nines, A(2) has 5 nines and A(3) has 6 nines.
As you understand I'm a newbie in Matlab..
Regards, Dimitris

4 comentarios

Be careful, as I wonder if this may be in respect to a Project Euler problem, or something like that. If you are hoping to work with numbers with many digits, don't forget that double precision is limited to roughly 16 significant digits.
Dear John,
No I have calculated the availability of a system. The nines represent the availability of the system. So, the 0.9 is 36.5 days per year down time, the 0.99 is 3.65 days per year down time etc and the 0.999999 is 31.5 seconds per year down time. I want to plot a figure that will give the nines of every system.
For example from array A = [0.999989023, 0.999994839, 0.999999751]
I want to calculate the Array B that will have the values
B = [4.89, 5.48, 6,76]
Thank you again for the help, Dimitris
Well, if that is what you want, then my solution gives it to you almost exactly! Just remove the floor, and it is exact.
-log10(1-A)
ans =
4.9595 5.2873 6.6038
Dear John,
You are correct!. I used what you suggested.
Thank you, Dimitris

Iniciar sesión para comentar.

 Respuesta aceptada

pfb
pfb el 2 de Mayo de 2015
Editada: pfb el 2 de Mayo de 2015
You could turn your numbers into strings, like e.g. in
st = sprintf('%1.10f',A(1))
maybe strip the trailing "0." (if they are all less than 1, in the form "0.999...")
st=st(3:end);
and then parse such string in a loop.
Or perhaps do this:
create a vector with (logical) ones in correspondence of the nines
aux1 = st=='9';
find the positions of the zeros (not nines)
i=find(~aux1)
Then the number of consecutive nines (after the decimal point) is one less than the position of the first zero (non-nine)
nnines=i(1)-1;

Más respuestas (3)

John D'Errico
John D'Errico el 2 de Mayo de 2015
Editada: John D'Errico el 2 de Mayo de 2015
Assuming that you are doing this for numbers that fit in the VERY limited dynamic range of a double, then I would do it very simply. No real need for string processing, which will be slow.
A = [0.999989023, 0.999994839, 0.999999751]
floor(-(log10(1 - A - eps)))
ans =
4 5 6
Again, this presumes that all of the elements of A are in the open interval (0,1).
A = [0.9 0.99 0.999 0.9999 0.99999 0.999999];
floor(-(log10(1 - A - eps)))
ans =
1 2 3 4 5 6
The reason for subtracting eps there is to cater to the cases where we had something like an "exact" 0.99, which would have been internally represented only approximately.
Here are some test cases to make sure that other values do not cause a problem.
A = [0.00000999 0.09 0.1415926535 .8999999999];
floor(-(log10(1 - A - eps)))
ans =
0 0 0 0
Again, I'd be very, very careful here. Do not hope that it will succeed for the number
A = 0.99999999999999999991234;
floor(-(log10(1 - A - eps)))
ans =
15 - 2i
Double precision arithmetic has limits. In fact, I cannot be sure that one of the string schemes may not be more accurate in some extreme case. But I know that they will be slower. :)
Image Analyst
Image Analyst el 2 de Mayo de 2015

If you have the Image Processing Toolbox you can use regionprops(). First I find all the 9's, including some you missed. Then I throw out single isolated 9's like there are in A(1) and A(2).

A = [0.999989023, 0.999994839, 0.999999751]
str = sprintf('%1.10f ', A)
nines = str == '9'
% Get lengths of stretches of all 9's of 1 or more:
measurements = regionprops(nines, 'Area');
B_all_nines = [measurements.Area]
% Throw out any that are a single 9
B_multiple_nines = B_all_nines; % Make a copy
B_multiple_nines(B_all_nines==1) = [] % Delete 1's

Of course you could compact that down to about 2 or 3 lines of code but I just made it super explicit so you can follow what it's doing. It shows:

B_all_nines =
     4     1     5     1     6
B_multiple_nines =
     4     5     6
Dear all,
Thank you very much for the answers. I see there is an active community here!
Regards, Dimitris

Categorías

Etiquetas

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by