Return largest number of decimal places in a vector of numbers

11 ビュー (過去 30 日間)
James Daniel
James Daniel 2023 年 9 月 19 日
コメント済み: James Daniel 2023 年 9 月 20 日
I'm trying to return the largest number of decimals from a vector of numbers. So say if I had x=[0.1,0.12,0.123,0.1234] I'd want an output of 4.
function [y] = maxdecimals(x)
for a = 1:length(x)
b(1,a) = strlength(num2str(abs(x(1,a))-floor(abs(x(1,a)))))-2;
% Creates vector with number of decimals
end
y = max(b);
% Finds maximum decimal number within vector
end
I'm getting a problem where if the number of decimal places is greater than 5, it doesn't seem to work. E.g. for x=[0.123456789,0.1,0.12,0.123] I get an output of 5, even though I should be getting 9.
For example, I input 0.123456789 and I get 5
strlength(num2str(abs(0.123456789)-floor(abs(0.123456789))))-2
ans =
5
Is there something about num2str that doesn't work for a certain length of numbers or is it something to do with the format limiting the number of decimal places?
>> num2str(abs(0.123456789)-floor(abs(0.123456789)))
ans =
'0.12346'

回答 (4 件)

Bruno Luong
Bruno Luong 2023 年 9 月 20 日
編集済み: Bruno Luong 2023 年 9 月 20 日
Good point from @Image Analyst, but I would add a comment:
All finite floating numbers when translated to decimal MUST eventually finish by 0 sequence.
x = [0.123456789,0.1,0.12,0.123];
fprintf('%.100f\n', x)
0.1234567889999999973360544913703051861375570297241210937500000000000000000000000000000000000000000000 0.1000000000000000055511151231257827021181583404541015625000000000000000000000000000000000000000000000 0.1199999999999999955591079014993738383054733276367187500000000000000000000000000000000000000000000000 0.1229999999999999982236431605997495353221893310546875000000000000000000000000000000000000000000000000
Why? because they are sum of power 2, and each power 2 can be written exactly in 10 base with finite number of digits, since 2 divides 10.
So actually the answer [9 1 2 3] for the above x is wrong, strictly speaking.
The correct answer is
x = [0.123456789,0.1,0.12,0.123];
s = arrayfun(@(x)sprintf('%.150f', x), x, 'unif', 0);
truedigitlength = cellfun(@(s) find(s~='0',1,'last')-2, s)
truedigitlength = 1×4
56 55 53 52
To get the wanted [9 1 2 3] output, one needs to specify the length for truncation and rounding in 10 base, e.g. around 15, 16 (-log10(eps)), which is kind of arbitrary definition. and likely to fail for numbers "small" x (with log10(x) << -1).
  2 件のコメント
Image Analyst
Image Analyst 2023 年 9 月 20 日
@Bruno Luong thanks for clarifying and expanding. I think this is the best and most accurate answer posted so far.
James Daniel
James Daniel 2023 年 9 月 20 日
@Bruno Luong I agree with @Image Analyst this is great clarification, thank you for your help

サインインしてコメントする。


Stephen23
Stephen23 2023 年 9 月 19 日
編集済み: Stephen23 2023 年 9 月 19 日
x = [0.123456789,0.1,0.12,0.123];
n = strlength(compose("%.15g",rem(abs(x),1)))-2
n = 1×4
9 1 2 3

Bruno Luong
Bruno Luong 2023 年 9 月 19 日
編集済み: Bruno Luong 2023 年 9 月 19 日
Check out the second input of num2str in the doc (in general always read the doc throughly most of the time the answer is right there).

Image Analyst
Image Analyst 2023 年 9 月 19 日
All double numbers have the same number of decimal points, unless they're rounded, because they're all 64 bit numbers. Watch:
x = [0.123456789,0.1,0.12,0.123];
fprintf('%.50f\n', x)
0.12345678899999999733605449137030518613755702972412 0.10000000000000000555111512312578270211815834045410 0.11999999999999999555910790149937383830547332763672 0.12299999999999999822364316059974953532218933105469

製品


リリース

R2022b

Community Treasure Hunt

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

Start Hunting!

Translated by