Reputation: 33
I want to implement a version of Benford's law (http://en.wikipedia.org/wiki/Benford%27s_law) that basically asks for the first digit of a number to do analysis on the distribution.
1934---> 1
0.04 ---> 4
-56 ---> 5
How do you do this in MATLAB?
Upvotes: 3
Views: 1626
Reputation: 124563
Let me add another string-based solution (vectorized as well):
FirstDigit = @(n) sscanf(num2str(abs(n(:)),'%e'), '%1d', numel(n));
and tested on the cases mentioned here:
>> FirstDigit( [1934 0.04 -56 eps(realmin)] )
ans =
1
4
5
4
Upvotes: 0
Reputation: 125874
A few ways you can do this...
Using REGEXP:
wholeNumber = 1934; %# Your number
numberString = num2str(wholeNumber,16); %# Convert to a string
matches = regexp(numberString,'[1-9]','match'); %# Find matches
firstNumber = str2double(matches{1}); %# Convert the first match to a double
Using ISMEMBER:
wholeNumber = 0.04; %# Your number
numberString = num2str(wholeNumber,16); %# Convert to a string
isInSet = ismember(numberString,'123456789'); %# Find numbers that are
%# between 1 and 9
numberIndex = find(isInSet,1); %# Get the first number index
firstNumber = str2double(numberString(numberIndex)); %# Convert to a double
EDIT:
Some discussion of this topic has arisen on one of the MathWorks blogs. Some interesting additional solutions are provided there. One issue that was brought up was having vectorized solutions, so here's one vectorized version I came up with:
numberVector = [1934 0.04 -56];
numberStrings = cellstr(num2str(numberVector(:),16));
firstIndices = regexp(numberStrings,'[1-9]','once');
firstNumbers = cellfun(@(s,i) s(i),numberStrings,firstIndices);
Upvotes: 2
Reputation: 6707
function res = first_digit(number)
number = abs(number);
res = floor(number / (10 ^ floor(log10(number))));
end
It works for all real numbers (see gnovice's comment for an extreme case)
Upvotes: 4
Reputation: 7458
Using log10 and floor built in functions,
floor(x./10.^floor(log10(x)))
returns the first digit of all elements in an array as well.
Upvotes: 1