【问题标题】:How to implement Benford's law in MATLAB如何在 MATLAB 中实现本福德定律
【发布时间】:2010-04-08 18:13:17
【问题描述】:

我想实现一个版本的本福德定律 (http://en.wikipedia.org/wiki/Benford%27s_law) 这基本上要求一个数字的第一位数字来对分布进行分析。

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

你如何在 MATLAB 中做到这一点?

【问题讨论】:

    标签: matlab benfords-law


    【解决方案1】:
    function res = first_digit(number)
        number = abs(number);
        res = floor(number / (10 ^ floor(log10(number))));
    end

    它适用于所有实数(有关极端情况,请参阅 gnovice 的评论)

    【讨论】:

    • 哎呀,我保证没有抄袭你的答案,亚辛!你一定是在我想办法解决问题的时候发帖的。 +1 考虑使用 abs() 来掩盖那些讨厌的负面因素。
    • +1:我知道可能有某种数学方法可以做到这一点,但我想到的第一个解决方案是基于字符串的。
    • @gnovive:谢谢。更正了!
    • 其实我刚刚发现了一个极端情况,这个方案失败了,但是字符串方案有效。试试number = eps(realmin)。诚然,这不是您会遇到的可能场景。我只是看到解决方案在极值上的表现如何。
    【解决方案2】:

    有几种方法可以做到这一点...

    • 使用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
      

    编辑:

    the MathWorks blogs 之一上出现了有关此主题的一些讨论。那里提供了一些有趣的附加解决方案。提出的一个问题是矢量化解决方案,所以这是我想出的一个矢量化版本:

    numberVector = [1934 0.04 -56];
    numberStrings = cellstr(num2str(numberVector(:),16));
    firstIndices = regexp(numberStrings,'[1-9]','once');
    firstNumbers = cellfun(@(s,i) s(i),numberStrings,firstIndices);
    

    【讨论】:

      【解决方案3】:

      使用 log10 和 floor 内置函数,

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

      也返回数组中所有元素的第一位。

      【讨论】:

        【解决方案4】:

        让我添加另一个基于字符串的解决方案(也是矢量化的):

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

        并在此处提到的案例中进行了测试:

        >> FirstDigit( [1934 0.04 -56 eps(realmin)] )
        ans =
             1
             4
             5
             4
        

        【讨论】:

          猜你喜欢
          • 2013-04-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-06-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多