如何在 MATLAB 中实现本福德定律

发布于 2024-08-28 00:35:35 字数 266 浏览 6 评论 0原文

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

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

在 MATLAB 中如何做到这一点?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

尘世孤行 2024-09-04 00:35:35
function res = first_digit(number)
    number = abs(number);
    res = floor(number / (10 ^ floor(log10(number))));
end

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

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)

审判长 2024-09-04 00:35:35

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

  • 使用 正则表达式

    整数 = 1934; %# 你的电话号码
    numberString = num2str(wholeNumber,16); %# 转换为字符串
    matches = regexp(numberString,'[1-9]','match'); %# 查找匹配项
    FirstNumber = str2double(匹配{1}); %# 将第一个匹配转换为双精度
    
  • 使用ISMEMBER

    整数 = 0.04; %# 你的电话号码
    numberString = num2str(wholeNumber,16); %# 转换为字符串
    isInSet = ismember(numberString,'123456789'); %# 查找以下数字
                                                   %# 1 到 9 之间
    numberIndex = find(isInSet,1); %# 获取第一个数字索引
    第一个数字 = str2double(numberString(numberIndex)); %# 转换为双精度数
    

编辑:

对此主题的一些讨论已出现在 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);

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);
花期渐远 2024-09-04 00:35:35

使用 log10 和 Floor 内置函数,

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

还返回数组中所有元素的第一个数字。

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.

小…楫夜泊 2024-09-04 00:35:35

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

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

并在此处提到的情况下进行测试:

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

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文