Как реализовать закон Бенфорда в MATLAB - PullRequest
3 голосов
/ 08 апреля 2010

Я хочу реализовать версию закона Бенфорда (http://en.wikipedia.org/wiki/Benford%27s_law) который в основном запрашивает первую цифру числа для анализа распределения.

1934---> 1
0.04 ---> 4
-56 ---> 5

Как вы делаете это в MATLAB?

Ответы [ 4 ]

4 голосов
/ 08 апреля 2010
function res = first_digit(number)
    number = abs(number);
    res = floor(number / (10 ^ floor(log10(number))));
end

Это работает для всех действительных чисел (см. Комментарий gnovice для крайнего случая)

2 голосов
/ 08 апреля 2010

Несколько способов сделать это ...

  • Использование 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
    
  • Использование 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:

Некоторое обсуждение этой темы возникло на одном из блогов MathWorks . Там представлены некоторые интересные дополнительные решения. Одна проблема, которая была поднята, имела векторизованные решения, поэтому вот одна векторизованная версия, которую я придумал:

numberVector = [1934 0.04 -56];
numberStrings = cellstr(num2str(numberVector(:),16));
firstIndices = regexp(numberStrings,'[1-9]','once');
firstNumbers = cellfun(@(s,i) s(i),numberStrings,firstIndices);
1 голос
/ 08 апреля 2010

Используя log10 и встроенные функции пола,

floor(x./10.^floor(log10(x)))

возвращает также первую цифру всех элементов в массиве.

0 голосов
/ 21 октября 2011

Позвольте мне добавить еще одно решение на основе строк (также векторизованное):

FirstDigit = @(n) sscanf(num2str(abs(n(:)),'%e'), '%1d', numel(n));

и проверено на случаях, упомянутых здесь:

>> FirstDigit( [1934 0.04 -56 eps(realmin)] )
ans =
     1
     4
     5
     4
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...