Update all new Tasks

This commit is contained in:
Ingy döt Net 2015-02-20 09:02:09 -05:00
parent 00a190b0a6
commit 91df62d461
5697 changed files with 93386 additions and 804 deletions

View file

@ -0,0 +1,18 @@
{{Wikipedia|Benford's_law}}
'''Benford's law''', also called the '''first-digit law''', refers to the frequency distribution of digits in many (but not all) real-life sources of data. In this distribution, the number 1 occurs as the first digit about 30% of the time, while larger numbers occur in that position less frequently: 9 as the first digit less than 5% of the time. This distribution of first digits is the same as the widths of gridlines on a logarithmic scale. Benford's law also concerns the expected distribution for digits beyond the first, which approach a uniform distribution.
This result has been found to apply to a wide variety of data sets, including electricity bills, street addresses, stock prices, population numbers, death rates, lengths of rivers, physical and mathematical constants, and processes described by power laws (which are very common in nature). It tends to be most accurate when values are distributed across multiple orders of magnitude.
A set of numbers is said to satisfy Benford's law if the leading digit <math>d</math> (<math>d \in \{1, \ldots, 9\}</math>) occurs with probability
:<math>P(d) = \log_{10}(d+1)-\log_{10}(d) = \log_{10}\left(1+\frac{1}{d}\right)</math>
For this task, write (a) routine(s) to calculate the distribution of first significant (non-zero) digits in a collection of numbers, then display the actual vs. expected distribution in the way most convenient for your language (table / graph / histogram / whatever).
Use the first 1000 numbers from the Fibonacci sequence as your data set. No need to show how the Fibonacci numbers are obtained. You can [[Fibonacci sequence|generate]] them or load them [http://www.ibiblio.org/pub/docs/books/gutenberg/etext01/fbncc10.txt from a file]; whichever is easiest. Display your actual vs expected distribution.
''For extra credit:'' Show the distribution for one other set of numbers from a page on Wikipedia. State which Wikipedia page it can be obtained from and what the set enumerates. Again, no need to display the actual list of numbers or the code to load them.
;<nowiki>See also:</nowiki>
* [http://www.numberphile.com/videos/benfords_law.html numberphile.com].
* A starting page on Wolfram Mathworld is {{Wolfram|Benfords|Law}}.

View file

@ -0,0 +1,27 @@
# syntax: GAWK -f BENFORDS_LAW.AWK
BEGIN {
n = 1000
for (i=1; i<=n; i++) {
arr[substr(fibonacci(i),1,1)]++
}
print("digit expected observed deviation")
for (i=1; i<=9; i++) {
expected = log10(i+1) - log10(i)
actual = arr[i] / n
deviation = expected - actual
printf("%5d %8.4f %8.4f %9.4f\n",i,expected*100,actual*100,abs(deviation*100))
}
exit(0)
}
function fibonacci(n, a,b,c,i) {
a = 0
b = 1
for (i=1; i<=n; i++) {
c = a + b
a = b
b = c
}
return(c)
}
function abs(x) { if (x >= 0) { return x } else { return -x } }
function log10(x) { return log(x)/log(10) }

View file

@ -0,0 +1,49 @@
with Ada.Text_IO, Ada.Numerics.Generic_Elementary_Functions;
procedure Benford is
subtype Nonzero_Digit is Natural range 1 .. 9;
function First_Digit(S: String) return Nonzero_Digit is
(if S(S'First) in '1' .. '9'
then Nonzero_Digit'Value(S(S'First .. S'First))
else First_Digit(S(S'First+1 .. S'Last)));
package N_IO is new Ada.Text_IO.Integer_IO(Natural);
procedure Print(D: Nonzero_Digit; Counted, Sum: Natural) is
package Math is new Ada.Numerics.Generic_Elementary_Functions(Float);
package F_IO is new Ada.Text_IO.Float_IO(Float);
Actual: constant Float := Float(Counted) / Float(Sum);
Expected: constant Float := Math.Log(1.0 + 1.0 / Float(D), Base => 10.0);
Deviation: constant Float := abs(Expected-Actual);
begin
N_IO.Put(D, 5);
N_IO.Put(Counted, 14);
F_IO.Put(Float(Sum)*Expected, Fore => 16, Aft => 1, Exp => 0);
F_IO.Put(100.0*Actual, Fore => 9, Aft => 2, Exp => 0);
F_IO.Put(100.0*Expected, Fore => 11, Aft => 2, Exp => 0);
F_IO.Put(100.0*Deviation, Fore => 13, Aft => 2, Exp => 0);
end Print;
Cnt: array(Nonzero_Digit) of Natural := (1 .. 9 => 0);
D: Nonzero_Digit;
Sum: Natural := 0;
Counter: Positive;
begin
while not Ada.Text_IO.End_Of_File loop
-- each line in the input file holds Counter, followed by Fib(Counter)
N_IO.Get(Counter);
-- Counter and skip it, we just don't need it
D := First_Digit(Ada.Text_IO.Get_Line);
-- read the rest of the line and extract the first digit
Cnt(D) := Cnt(D)+1;
Sum := Sum + 1;
end loop;
Ada.Text_IO.Put_Line(" Digit Found[total] Expected[total] Found[%]"
& " Expected[%] Difference[%]");
for I in Nonzero_Digit loop
Print(I, Cnt(I), Sum);
Ada.Text_IO.New_Line;
end loop;
end Benford;

View file

@ -0,0 +1 @@
-- N_IO.Get(Counter);

View file

@ -0,0 +1,95 @@
text
sum(text a, text b)
{
data d;
integer e, f, n, r;
e = length(a);
f = length(b);
r = 0;
n = min(e, f);
while (n) {
n -= 1;
e -= 1;
f -= 1;
r += a[e] - '0';
r += b[f] - '0';
b_insert(d, 0, r % 10 + '0');
r /= 10;
}
if (f) {
e = f;
a = b;
}
while (e) {
e -= 1;
r += a[e] - '0';
b_insert(d, 0, r % 10 + '0');
r /= 10;
}
if (r) {
b_insert(d, 0, r + '0');
}
return b_string(d);
}
text
fibs(list l, integer n)
{
integer c, i;
text a, b, w;
l_r_integer(l, 1, 1);
a = "0";
b = "1";
i = 1;
while (i < n) {
w = sum(a, b);
a = b;
b = w;
c = w[0] - '0';
l_r_integer(l, c, 1 + l_q_integer(l, c));
i += 1;
}
return w;
}
integer
main(void)
{
integer i, n;
list f;
real m;
n = 1000;
i = 10;
while (i) {
i -= 1;
lb_p_integer(f, 0);
}
fibs(f, n);
m = 100r / n;
o_text("\t\texpected\t found\n");
i = 0;
while (i < 9) {
i += 1;
o_winteger(8, i);
o_wpreal(16, 3, 3, 100 * log10(1 + 1r / i));
o_wpreal(16, 3, 3, l_q_integer(f, i) * m);
o_text("\n");
}
return 0;
}

View file

@ -0,0 +1,43 @@
SetBatchLines, -1
fib := NStepSequence(1, 1, 2, 1000)
Out := "Digit`tExpected`tObserved`tDeviation`n"
n := []
for k, v in fib
d := SubStr(v, 1, 1)
, n[d] := n[d] ? n[d] + 1 : 1
for k, v in n
Exppected := 100 * Log(1+ (1 / k))
, Observed := (v / fib.MaxIndex()) * 100
, Out .= k "`t" Exppected "`t" Observed "`t" Abs(Exppected - Observed) "`n"
MsgBox, % Out
NStepSequence(v1, v2, n, k) {
a := [v1, v2]
Loop, % k - 2 {
a[j := A_Index + 2] := 0
Loop, % j < n + 2 ? j - 1 : n
a[j] := BigAdd(a[j - A_Index], a[j])
}
return, a
}
BigAdd(a, b) {
if (StrLen(b) > StrLen(a))
t := a, a := b, b := t
LenA := StrLen(a) + 1, LenB := StrLen(B) + 1, Carry := 0
Loop, % LenB - 1
Sum := SubStr(a, LenA - A_Index, 1) + SubStr(B, LenB - A_Index, 1) + Carry
, Carry := Sum // 10
, Result := Mod(Sum, 10) . Result
Loop, % I := LenA - LenB {
if (!Carry) {
Result := SubStr(a, 1, I) . Result
break
}
Sum := SubStr(a, I, 1) + Carry
, Carry := Sum // 10
, Result := Mod(Sum, 10) . Result
, I--
}
return, (Carry ? Carry : "") . Result
}

View file

@ -0,0 +1,62 @@
//to cope with the big numbers , I used the Class Library for Numbers( CLN )
//if used prepackaged you can compile writing "g++ -std=c++11 -lcln yourprogram.cpp -o yourprogram"
#include <cln/integer.h>
#include <cln/integer_io.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <iomanip>
#include <sstream>
#include <string>
#include <cstdlib>
#include <cmath>
#include <map>
using namespace cln ;
class NextNum {
public :
NextNum ( cl_I & a , cl_I & b ) : first( a ) , second ( b ) { }
cl_I operator( )( ) {
cl_I result = first + second ;
first = second ;
second = result ;
return result ;
}
private :
cl_I first ;
cl_I second ;
} ;
void findFrequencies( const std::vector<cl_I> & fibos , std::map<int , int> &numberfrequencies ) {
for ( cl_I bignumber : fibos ) {
std::ostringstream os ;
fprintdecimal ( os , bignumber ) ;//from header file cln/integer_io.h
int firstdigit = std::atoi( os.str( ).substr( 0 , 1 ).c_str( )) ;
auto result = numberfrequencies.insert( std::make_pair( firstdigit , 1 ) ) ;
if ( ! result.second )
numberfrequencies[ firstdigit ]++ ;
}
}
int main( ) {
std::vector<cl_I> fibonaccis( 1000 ) ;
fibonaccis[ 0 ] = 0 ;
fibonaccis[ 1 ] = 1 ;
cl_I a = 0 ;
cl_I b = 1 ;
//since a and b are passed as references to the generator's constructor
//they are constantly changed !
std::generate_n( fibonaccis.begin( ) + 2 , 998 , NextNum( a , b ) ) ;
std::cout << std::endl ;
std::map<int , int> frequencies ;
findFrequencies( fibonaccis , frequencies ) ;
std::cout << " found expected\n" ;
for ( int i = 1 ; i < 10 ; i++ ) {
double found = static_cast<double>( frequencies[ i ] ) / 1000 ;
double expected = std::log10( 1 + 1 / static_cast<double>( i )) ;
std::cout << i << " :" << std::setw( 16 ) << std::right << found * 100 << " %" ;
std::cout.precision( 3 ) ;
std::cout << std::setw( 26 ) << std::right << expected * 100 << " %\n" ;
}
return 0 ;
}

View file

@ -0,0 +1,64 @@
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
float *benford_distribution(void)
{
static float prob[9];
for (int i = 1; i < 10; i++)
prob[i - 1] = log10f(1 + 1.0 / i);
return prob;
}
float *get_actual_distribution(char *fn)
{
FILE *input = fopen(fn, "r");
if (!input)
{
perror("Can't open file");
exit(EXIT_FAILURE);
}
int tally[9] = { 0 };
char c;
int total = 0;
while ((c = getc(input)) != EOF)
{
/* get the first nonzero digit on the current line */
while (c < '1' || c > '9')
c = getc(input);
tally[c - '1']++;
total++;
/* discard rest of line */
while ((c = getc(input)) != '\n' && c != EOF)
;
}
fclose(input);
static float freq[9];
for (int i = 0; i < 9; i++)
freq[i] = tally[i] / (float) total;
return freq;
}
int main(int argc, char **argv)
{
if (argc != 2)
{
printf("Usage: benford <file>\n");
return EXIT_FAILURE;
}
float *actual = get_actual_distribution(argv[1]);
float *expected = benford_distribution();
puts("digit\tactual\texpected");
for (int i = 0; i < 9; i++)
printf("%d\t%.3f\t%.3f\n", i + 1, actual[i], expected[i]);
return EXIT_SUCCESS;
}

View file

@ -0,0 +1,21 @@
fibgen = () ->
a = 1; b = 0
return () ->
([a, b] = [b, a+b])[1]
leading = (x) -> x.toString().charCodeAt(0) - 0x30
f = fibgen()
benford = (0 for i in [1..9])
benford[leading(f()) - 1] += 1 for i in [1..1000]
log10 = (x) -> Math.log(x) * Math.LOG10E
actual = benford.map (x) -> x * 0.001
expected = (log10(1 + 1/x) for x in [1..9])
console.log "Leading digital distribution of the first 1,000 Fibonacci numbers"
console.log "Digit\tActual\tExpected"
for i in [1..9]
console.log i + "\t" + actual[i - 1].toFixed(3) + '\t' + expected[i - 1].toFixed(3)

View file

@ -0,0 +1,43 @@
(defun calculate-distribution (numbers)
"Return the frequency distribution of the most significant nonzero
digits in the given list of numbers. The first element of the list
is the frequency for digit 1, the second for digit 2, and so on."
(defun nonzero-digit-p (c)
"Check whether the character is a nonzero digit"
(and (digit-char-p c) (char/= c #\0)))
(defun first-digit (n)
"Return the most significant nonzero digit of the number or NIL if
there is none."
(let* ((s (write-to-string n))
(c (find-if #'nonzero-digit-p s)))
(when c
(digit-char-p c))))
(let ((tally (make-array 9 :element-type 'integer :initial-element 0)))
(loop for n in numbers
for digit = (first-digit n)
when digit
do (incf (aref tally (1- digit))))
(loop with total = (length numbers)
for digit-count across tally
collect (/ digit-count total))))
(defun calculate-benford-distribution ()
"Return the frequency distribution according to Benford's law.
The first element of the list is the probability for digit 1, the second
element the probability for digit 2, and so on."
(loop for i from 1 to 9
collect (log (1+ (/ i)) 10)))
(defun benford (numbers)
"Print a table of the actual and expected distributions for the given
list of numbers."
(let ((actual-distribution (calculate-distribution numbers))
(expected-distribution (calculate-benford-distribution)))
(write-line "digit actual expected")
(format T "~:{~3D~9,3F~8,3F~%~}"
(map 'list #'list '(1 2 3 4 5 6 7 8 9)
actual-distribution
expected-distribution))))

View file

@ -0,0 +1,24 @@
import std.stdio, std.range, std.math, std.conv, std.bigint;
double[2][9] benford(R)(R seq) if (isForwardRange!R && !isInfinite!R) {
typeof(return) freqs = 0;
uint seqLen = 0;
foreach (d; seq)
if (d != 0) {
freqs[d.text[0] - '1'][1]++;
seqLen++;
}
foreach (immutable i, ref p; freqs)
p = [log10(1.0 + 1.0 / (i + 1)), p[1] / seqLen];
return freqs;
}
void main() {
auto fibs = recurrence!q{a[n - 1] + a[n - 2]}(1.BigInt, 1.BigInt);
writefln("%9s %9s %9s", "Actual", "Expected", "Deviation");
foreach (immutable i, immutable p; fibs.take(1000).benford)
writefln("%d: %5.2f%% | %5.2f%% | %5.4f%%",
i+1, p[1] * 100, p[0] * 100, abs(p[1] - p[0]) * 100);
}

View file

@ -0,0 +1,18 @@
import std.stdio, std.range, std.math, std.conv, std.bigint,
std.algorithm, std.array;
auto benford(R)(R seq) if (isForwardRange!R && !isInfinite!R) {
return seq.filter!q{a != 0}.map!q{a.text[0]-'1'}.array.sort().group;
}
void main() {
auto fibs = recurrence!q{a[n - 1] + a[n - 2]}(1.BigInt, 1.BigInt);
auto expected = iota(1, 10).map!(d => log10(1.0 + 1.0 / d));
enum N = 1_000;
writefln("%9s %9s %9s", "Actual", "Expected", "Deviation");
foreach (immutable i, immutable f; fibs.take(N).benford)
writefln("%d: %5.2f%% | %5.2f%% | %5.4f%%", i + 1,
f * 100.0 / N, expected[i] * 100,
abs((f / double(N)) - expected[i]) * 100);
}

View file

@ -0,0 +1,25 @@
-module( benfords_law ).
-export( [actual_distribution/1, distribution/1, task/0] ).
actual_distribution( Ns ) -> lists:foldl( fun first_digit_count/2, dict:new(), Ns ).
distribution( N ) -> math:log10( 1 + (1 / N) ).
task() ->
Total = 1000,
Fibonaccis = fib( Total ),
Actual_dict = actual_distribution( Fibonaccis ),
Keys = lists:sort( dict:fetch_keys( Actual_dict) ),
io:fwrite( "Digit Actual Benfords expected~n" ),
[io:fwrite("~p ~p ~p~n", [X, dict:fetch(X, Actual_dict) / Total, distribution(X)]) || X <- Keys].
fib( N ) -> fib( N, 0, 1, [] ).
fib( 0, Current, _, Acc ) -> lists:reverse( [Current | Acc] );
fib( N, Current, Next, Acc ) -> fib( N-1, Next, Current+Next, [Current | Acc] ).
first_digit_count( 0, Dict ) -> Dict;
first_digit_count( N, Dict ) ->
[Key | _] = erlang:integer_to_list( N ),
dict:update_counter( Key - 48, 1, Dict ).

View file

@ -0,0 +1,44 @@
: 3drop drop 2drop ;
: f2drop fdrop fdrop ;
: int-array create cells allot does> swap cells + ;
: 1st-fib 0e 1e ;
: next-fib ftuck f+ ;
: 1st-digit ( fp -- n )
pad 6 represent 3drop pad c@ [char] 0 - ;
10 int-array counts
: tally
0 counts 10 cells erase
1st-fib
1000 0 DO
1 fdup 1st-digit counts +!
next-fib
LOOP f2drop ;
: benford ( d -- fp )
s>f 1/f 1e f+ flog ;
: tab 9 emit ;
: heading ( -- )
cr ." Leading digital distribution of the first 1,000 Fibonacci numbers:"
cr ." Digit" tab ." Actual" tab ." Expected" ;
: .fixed ( n -- ) \ print count as decimal fraction
s>d <# # # # [char] . hold #s #> type space ;
: report ( -- )
precision 3 set-precision
heading
10 1 DO
cr i 3 .r
tab i counts @ .fixed
tab i benford f.
LOOP
set-precision ;
: compute-benford tally report ;

View file

@ -0,0 +1,9 @@
-*- mode: compilation; default-directory: "/tmp/" -*-
Compilation started at Sat May 18 01:13:00
a=./f && make $a && $a
f95 -Wall -ffree-form f.F -o f
0.301030010 0.176091254 0.124938756 9.69100147E-02 7.91812614E-02 6.69467747E-02 5.79919666E-02 5.11525236E-02 4.57575098E-02 THE LAW
0.300999999 0.177000001 0.125000000 9.60000008E-02 7.99999982E-02 6.70000017E-02 5.70000000E-02 5.29999994E-02 4.50000018E-02 LEADING FIBONACCI DIGIT
Compilation finished at Sat May 18 01:13:00

View file

@ -0,0 +1,69 @@
subroutine fibber(a,b,c,d)
! compute most significant digits, Fibonacci like.
implicit none
integer (kind=8), intent(in) :: a,b
integer (kind=8), intent(out) :: c,d
d = a + b
if (15 .lt. log10(float(d))) then
c = b/10
d = d/10
else
c = b
endif
end subroutine fibber
integer function leadingDigit(a)
implicit none
integer (kind=8), intent(in) :: a
integer (kind=8) :: b
b = a
do while (9 .lt. b)
b = b/10
end do
leadingDigit = transfer(b,leadingDigit)
end function leadingDigit
real function benfordsLaw(a)
implicit none
integer, intent(in) :: a
benfordsLaw = log10(1.0 + 1.0 / a)
end function benfordsLaw
program benford
implicit none
interface
subroutine fibber(a,b,c,d)
implicit none
integer (kind=8), intent(in) :: a,b
integer (kind=8), intent(out) :: c,d
end subroutine fibber
integer function leadingDigit(a)
implicit none
integer (kind=8), intent(in) :: a
end function leadingDigit
real function benfordsLaw(a)
implicit none
integer, intent(in) :: a
end function benfordsLaw
end interface
integer (kind=8) :: a, b, c, d
integer :: i, count(10)
data count/10*0/
a = 1
b = 1
do i = 1, 1001
count(leadingDigit(a)) = count(leadingDigit(a)) + 1
call fibber(a,b,c,d)
a = c
b = d
end do
write(6,*) (benfordsLaw(i),i=1,9),'THE LAW'
write(6,*) (count(i)/1000.0 ,i=1,9),'LEADING FIBONACCI DIGIT'
end program benford

View file

@ -0,0 +1,31 @@
package main
import (
"fmt"
"math"
)
func Fib1000() []float64 {
a, b, r := 0., 1., [1000]float64{}
for i := range r {
r[i], a, b = b, b, b+a
}
return r[:]
}
func main() {
show(Fib1000(), "First 1000 Fibonacci numbers")
}
func show(c []float64, title string) {
var f [9]int
for _, v := range c {
f[fmt.Sprintf("%g", v)[0]-'1']++
}
fmt.Println(title)
fmt.Println("Digit Observed Predicted")
for i, n := range f {
fmt.Printf(" %d %9.3f %8.3f\n", i+1, float64(n)/float64(len(c)),
math.Log10(1+1/float64(i+1)))
}
}

View file

@ -0,0 +1,17 @@
import qualified Data.Map as M
import Data.Char (digitToInt)
fstdigit :: Integer -> Int
fstdigit = digitToInt . head . show
n = 1000::Int
fibs = 1:1:zipWith (+) fibs (tail fibs)
fibdata = map fstdigit $ take n fibs
freqs = M.fromListWith (+) $ zip fibdata (repeat 1)
tab :: [(Int, Double, Double)]
tab = [(d,
(fromIntegral (M.findWithDefault 0 d freqs) /(fromIntegral n) ),
logBase 10.0 $ 1 + 1/(fromIntegral d) ) | d<-[1..9]]
main = print tab

View file

@ -0,0 +1,34 @@
global counts, total
procedure main()
counts := table(0)
total := 0.0
every benlaw(fib(1 to 1000))
every i := 1 to 9 do
write(i,": ",right(100*counts[string(i)]/total,9)," ",100*P(i))
end
procedure benlaw(n)
if counts[n ? (tab(upto('123456789')),move(1))] +:= 1 then total +:= 1
end
procedure P(d)
return log(1+1.0/d, 10)
end
procedure fib(n) # From Fibonacci Sequence task
return fibMat(n)[1]
end
procedure fibMat(n)
if n <= 0 then return [0,0]
if n = 1 then return [1,0]
fp := fibMat(n/2)
c := fp[1]*fp[1] + fp[2]*fp[2]
d := fp[1]*(fp[1]+2*fp[2])
if n%2 = 1 then return [c+d, d]
else return [d, c]
end

View file

@ -0,0 +1,36 @@
log10 =: 10&^.
benford =: log10@:(1+%)
assert '0.30 0.18 0.12 0.10 0.08 0.07 0.06 0.05 0.05' -: 5j2 ": benford >: i. 9
append_next_fib =: , +/@:(_2&{.)
assert 5 8 13 -: append_next_fib 5 8
leading_digits =: {.@":&>
assert '581' -: leading_digits 5 8 13x
count =: #/.~ /: ~.
assert 2 1 3 4 -: count 'XCXBAXACXC' NB. 2 A's, 1 B, 3 C's, and some X's.
normalize =: % +/
assert 1r3 2r3 -: normalize 1 2x
FIB =: append_next_fib ^: (1000-#) 1 1
LDF =: leading_digits FIB
TALLY_BY_KEY =: count LDF
assert 9 -: # TALLY_BY_KEY NB. If all of [1-9] are present then we know what the digits are.
mean =: +/ % #
center=: - mean
mp =: $:~ :(+/ .*)
num =: mp&:center
den =: %:@:(*&:(+/@:(*:@:center)))
r =: num % den NB. r is the LibreOffice correl function
assert '_0.982' -: 6j3 ": 1 2 3 r 6 5 3 NB. confirmed using LibreOffice correl function
assert '0.9999' -: 6j4 ": (normalize TALLY_BY_KEY) r benford >: i.9
assert '0.9999' -: 6j4 ": TALLY_BY_KEY r benford >: i.9 NB. Of course we don't need normalization

View file

@ -0,0 +1,41 @@
import java.math.BigInteger;
public class Benford {
private static interface NumberGenerator {
BigInteger[] getNumbers();
}
private static class FibonacciGenerator implements NumberGenerator {
public BigInteger[] getNumbers() {
final BigInteger[] fib = new BigInteger[ 1000 ];
fib[ 0 ] = fib[ 1 ] = BigInteger.ONE;
for ( int i = 2; i < fib.length; i++ )
fib[ i ] = fib[ i - 2 ].add( fib[ i - 1 ] );
return fib;
}
}
private final int[] firstDigits = new int[ 9 ];
private final int count;
private Benford( final NumberGenerator ng ) {
final BigInteger[] numbers = ng.getNumbers();
count = numbers.length;
for ( final BigInteger number : numbers )
firstDigits[ Integer.valueOf( number.toString().substring( 0, 1 ) ) - 1 ]++;
}
public String toString() {
final StringBuilder result = new StringBuilder();
for ( int i = 0; i < firstDigits.length; i++ )
result.append( i + 1 )
.append( '\t' ).append( firstDigits[ i ] / ( double )count )
.append( '\t' ).append( Math.log10( 1 + 1d / ( i + 1 ) ) )
.append( '\n' );
return result.toString();
}
public static void main( final String[] args ) {
System.out.println( new Benford( new FibonacciGenerator() ) );
}
}

View file

@ -0,0 +1,5 @@
fib(n) = ([one(n) one(n) ; one(n) zero(n)]^n)[1,2]
ben(l) = [count(x->x==i, map(n->string(n)[1],l)) for i='1':'9']./length(l)
benford(l) = [Number[1:9] ben(l) log10(1.+1./[1:9])]

View file

@ -0,0 +1,35 @@
dim bin(9)
N=1000
for i = 0 to N-1
num$ = str$(fiboI(i))
d=val(left$(num$,1))
'print num$, d
bin(d)=bin(d)+1
next
print
print "Digit", "Actual freq", "Expected freq"
for i = 1 to 9
print i, bin(i)/N, using("#.###", P(i))
next
function P(d)
P = log10(d+1)-log10(d)
end function
function log10(x)
log10 = log(x)/log(10)
end function
function fiboI(n)
a = 0
b = 1
for i = 1 to n
temp = a + b
a = b
b = temp
next i
fiboI = a
end function

View file

@ -0,0 +1,20 @@
actual = {}
expected = {}
for i = 1, 9 do
actual[i] = 0
expected[i] = math.log10(1 + 1 / i)
end
n = 0
file = io.open("fibs1000.txt", "r")
for line in file:lines() do
digit = string.byte(line, 1) - 48
actual[digit] = actual[digit] + 1
n = n + 1
end
file:close()
print("digit actual expected")
for i = 1, 9 do
print(i, actual[i] / n, expected[i])
end

View file

@ -0,0 +1,3 @@
fibdata = Array[First@IntegerDigits@Fibonacci@# &, 1000];
Table[{d, N@Count[fibdata, d]/Length@fibdata, Log10[1. + 1/d]}, {d, 1,
9}] // Grid

View file

@ -0,0 +1,41 @@
/* NetRexx */
options replace format comments java crossref symbols nobinary
runSample(arg)
return
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
method brenfordDeveation(nlist = Rexx[]) public static
observed = 0
loop n_ over nlist
d1 = n_.left(1)
if d1 = 0 then iterate n_
observed[d1] = observed[d1] + 1
end n_
say ' '.right(4) 'Observed'.right(11) 'Expected'.right(11) 'Deviation'.right(11)
loop n_ = 1 to 9
actual = (observed[n_] / (nlist.length - 1))
expect = Rexx(Math.log10(1 + 1 / n_))
deviat = expect - actual
say n_.right(3)':' (actual * 100).format(3, 6)'%' (expect * 100).format(3, 6)'%' (deviat * 100).abs().format(3, 6)'%'
end n_
return
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
method fibonacciList(size = 1000) public static returns Rexx[]
fibs = Rexx[size + 1]
fibs[0] = 0
fibs[1] = 1
loop n_ = 2 to size
fibs[n_] = fibs[n_ - 1] + fibs[n_ - 2]
end n_
return fibs
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
method runSample(arg) private static
parse arg n_ .
if n_ = '' then n_ = 1000
fibList = fibonacciList(n_)
say 'Fibonacci sequence to' n_
brenfordDeveation(fibList)
return

View file

@ -0,0 +1,9 @@
distribution(v)={
my(t=vector(9,n,sum(i=1,#v,v[i]==n)));
print("Digit\tActual\tExpected");
for(i=1,9,print(i, "\t", t[i], "\t", round(#v*(log(i+1)-log(i))/log(10))))
};
dist(f)=distribution(vector(1000,n,digits(f(n))[1]));
lucas(n)=fibonacci(n-1)+fibonacci(n+1);
dist(fibonacci)
dist(lucas)

View file

@ -0,0 +1,39 @@
(fofl, size, subrg):
Benford: procedure options(main); /* 20 October 2013 */
declare sc(1000) char(1), f(1000) float (16);
declare d fixed (1);
call Fibonacci(f);
call digits(sc, f);
put skip list ('digit expected obtained');
do d= 1 upthru 9;
put skip edit (d, log10(1 + 1/d), tally(sc, trim(d))/1000)
(f(3), 2 f(13,8) );
end;
Fibonacci: procedure (f);
declare f(*) float (16);
declare i fixed binary;
f(1), f(2) = 1;
do i = 3 to 1000;
f(i) = f(i-1) + f(i-2);
end;
end Fibonacci;
digits: procedure (sc, f);
declare sc(*) char(1), f(*) float (16);
sc = substr(trim(f), 1, 1);
end digits;
tally: procedure (sc, d) returns (fixed binary);
declare sc(*) char(1), d char(1);
declare (i, t) fixed binary;
t = 0;
do i = 1 to 1000;
if sc(i) = d then t = t + 1;
end;
return (t);
end tally;
end Benford;

View file

@ -0,0 +1,34 @@
WITH recursive
constant(val) AS
(
select 1000.
)
,
fib(a,b) AS
(
SELECT CAST(0 AS numeric), CAST(1 AS numeric)
UNION ALL
SELECT b,a+b
FROM fib
)
,
benford(first_digit, probability_real, probability_theoretical) AS
(
SELECT *,
CAST(log(1. + 1./CAST(first_digit AS INT)) AS NUMERIC(5,4)) probability_theoretical
FROM (
SELECT first_digit, CAST(COUNT(1)/(select val from constant) AS NUMERIC(5,4)) probability_real FROM
(
SELECT SUBSTRING(CAST(a AS VARCHAR(100)),1,1) first_digit
FROM fib
WHERE SUBSTRING(CAST(a AS VARCHAR(100)),1,1) <> '0'
LIMIT (select val from constant)
) t
GROUP BY first_digit
) f
ORDER BY first_digit ASC
)
select *
from benford cross join
(select cast(corr(probability_theoretical,probability_real) as numeric(5,4)) correlation
from benford) c

View file

@ -0,0 +1,14 @@
sub benford(@a) { bag +« @a».comb: /<( <[ 1..9 ]> )> <[ , . \d ]>*/ }
sub show(%distribution) {
printf "%9s %9s %s\n", <Actual Expected Deviation>;
for 1 .. 9 -> $digit {
my $actual = %distribution{$digit} * 100 / [+] %distribution.values;
my $expected = (1 + 1 / $digit).log(10) * 100;
printf "%d: %5.2f%% | %5.2f%% | %.2f%%\n",
$digit, $actual, $expected, abs($expected - $actual);
}
}
multi MAIN($file) { show benford $file.IO.lines }
multi MAIN() { show benford ( 1, 1, 2, *+* ... * )[^1000] }

View file

@ -0,0 +1,25 @@
#!/usr/bin/perl
use strict ;
use warnings ;
use POSIX qw( log10 ) ;
my @fibonacci = ( 0 , 1 ) ;
while ( @fibonacci != 1000 ) {
push @fibonacci , $fibonacci[ -1 ] + $fibonacci[ -2 ] ;
}
my @actuals ;
my @expected ;
for my $i( 1..9 ) {
my $sum = 0 ;
map { $sum++ if $_ =~ /\A$i/ } @fibonacci ;
push @actuals , $sum / 1000 ;
push @expected , log10( 1 + 1/$i ) ;
}
print " Observed Expected\n" ;
for my $i( 1..9 ) {
print "$i : " ;
my $result = sprintf ( "%.2f" , 100 * $actuals[ $i - 1 ] ) ;
printf "%11s %%" , $result ;
$result = sprintf ( "%.2f" , 100 * $expected[ $i - 1 ] ) ;
printf "%15s %%\n" , $result ;
}

View file

@ -0,0 +1,44 @@
%_________________________________________________________________
% Does the Fibonacci sequence follow Benford's law?
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
% Fibonacci sequence generator
fib(C, [P,S], C, N) :- N is P + S.
fib(C, [P,S], Cv, V) :- succ(C, Cn), N is P + S, !, fib(Cn, [S,N], Cv, V).
fib(0, 0).
fib(1, 1).
fib(C, N) :- fib(2, [0,1], C, N). % Generate from 3rd sequence on
% The benford law calculated
benford(D, Val) :- Val is log10(1+1/D).
% Retrieves the first characters of the first 1000 fibonacci numbers
% (excluding zero)
firstchar(V) :-
fib(C,N), N =\= 0, atom_chars(N, [Ch|_]), number_chars(V, [Ch]),
(C>999-> !; true).
% Increment the n'th list item (1 based), result -> third argument.
incNth(1, [Dh|Dt], [Ch|Dt]) :- !, succ(Dh, Ch).
incNth(H, [Dh|Dt], [Dh|Ct]) :- succ(Hn, H), !, incNth(Hn, Dt, Ct).
% Calculate the frequency of the all the list items
freq([], D, D).
freq([H|T], D, C) :- incNth(H, D, L), !, freq(T, L, C).
freq([H|T], Freq) :-
length([H|T], Len), min_list([H|T], Min), max_list([H|T], Max),
findall(0, between(Min,Max,_), In),
freq([H|T], In, F), % Frequency stored in F
findall(N, (member(V, F), N is V/Len), Freq). % Normalise F->Freq
% Output the results
writeHdr :-
format('~t~w~15| - ~t~w\n', ['Benford', 'Measured']).
writeData(Benford, Freq) :-
format('~t~2f%~15| - ~t~2f%\n', [Benford*100, Freq*100]).
go :- % main goal
findall(B, (between(1,9,N), benford(N,B)), Benford),
findall(C, firstchar(C), Fc), freq(Fc, Freq),
writeHdr, maplist(writeData, Benford, Freq).

View file

@ -0,0 +1,39 @@
from __future__ import division
from itertools import islice, count
from collections import Counter
from math import log10
from random import randint
expected = [log10(1+1/d) for d in range(1,10)]
def fib():
a,b = 1,1
while True:
yield a
a,b = b,a+b
# powers of 3 as a test sequence
def power_of_threes():
return (3**k for k in count(0))
def heads(s):
for a in s: yield int(str(a)[0])
def show_dist(title, s):
c = Counter(s)
size = sum(c.values())
res = [c[d]/size for d in range(1,10)]
print("\n%s Benfords deviation" % title)
for r, e in zip(res, expected):
print("%5.1f%% %5.1f%% %5.1f%%" % (r*100., e*100., abs(r - e)*100.))
def rand1000():
while True: yield randint(1,9999)
if __name__ == '__main__':
show_dist("fibbed", islice(heads(fib()), 1000))
show_dist("threes", islice(heads(power_of_threes()), 1000))
# just to show that not all kind-of-random sets behave like that
show_dist("random", islice(heads(rand1000()), 10000))

View file

@ -0,0 +1,31 @@
pbenford <- function(d){
return(log10(1+(1/d)))
}
get_lead_digit <- function(number){
return(as.numeric(substr(number,1,1)))
}
fib_iter <- function(n){
first <- 1
second <- 0
for(i in 1:n){
sum <- first + second
first <- second
second <- sum
}
return(sum)
}
fib_sequence <- mapply(fib_iter,c(1:1000))
lead_digits <- mapply(get_lead_digit,fib_sequence)
observed_frequencies <- table(lead_digits)/1000
expected_frequencies <- mapply(pbenford,c(1:9))
data <- data.frame(observed_frequencies,expected_frequencies)
colnames(data) <- c("digit","obs.frequency","exp.frequency")
dev_percentage <- abs((data$obs.frequency-data$exp.frequency)*100)
data <- data.frame(data,dev_percentage)
print(data)

1
Task/Benfords-law/README Normal file
View file

@ -0,0 +1 @@
Data source: http://rosettacode.org/wiki/Benford's_law

View file

@ -0,0 +1,33 @@
/*REXX program demonstrates some common trig functions (30 digits shown)*/
numeric digits 50 /*use only 50 digits for LN, LOG.*/
parse arg N .; if N=='' then N=1000 /*allow sample size specification*/
/*══════════════apply Benford's law to Fibonacci numbers.*/
@.=1; do j=3 to N; jm1=j-1; jm2=j-2; @.j=@.jm2+@.jm1; end /*j*/
call show_results "Benford's law applied to" N 'Fibonacci numbers'
/*══════════════apply Benford's law to prime numbers. */
p=0; do j=2 until p==N; if \isPrime(j) then iterate; p=p+1; @.p=j;end
call show_results "Benford's law applied to" N 'prime numbers'
/*══════════════apply Benford's law to factorials. */
do j=1 for N; @.j=!(j); end /*j*/
call show_results "Benford's law applied to" N 'factorial products'
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────SHOW_RESULTS subroutine─────────────*/
show_results: w1=max(length('observed'),length(N-2)) ; say
pad=' '; w2=max(length('expected' ),length(N ))
say pad 'digit' pad center('observed',w1) pad center('expected',w2)
say pad '' pad center('',w1,'') pad center('',w2,'') pad arg(1)
!.=0; do j=1 for N; _=left(@.j,1); !._=!._+1; end /*get 1st digits.*/
do k=1 for 9 /*show results for Fibonacci nums*/
say pad center(k,5) pad center(format(!.k/N,,length(N-2)),w1),
pad center(format(log(1+1/k),,length(N)+2),w2)
end /*k*/
return
/*──────────────────────────────────one─line subroutines───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────*/
!: procedure; parse arg x; !=1; do j=2 to x; !=!*j; end /*j*/; return !
e: return 2.7182818284590452353602874713526624977572470936999595749669676277240766303535
isprime: procedure; parse arg x; if wordpos(x,'2 3 5 7')\==0 then return 1; if x//2==0 then return 0; if x//3==0 then return 0; do j=5 by 6 until j*j>x; if x//j==0 then return 0; if x//(j+2)==0 then return 0; end; return 1
ln10:return 2.30258509299404568401799145468436420760110148862877297603332790096757260967735248023599720508959829834196778404228624863340952546508280675666628736909878168948290720832555468084379989482623319852839350530896538
ln:procedure expose $.;parse arg x,f;if x==10 then do;_=ln10();xx=format(_);if xx\==_ then return xx;end;call e;ig=x>1.5;is=1-2*(ig\==1);ii=0;xx=x;return .ln_comp()
.ln_comp:do while ig&xx>1.5|\ig&xx<.5;_=e();do k=-1;iz=xx*_**-is;if k>=0&(ig&iz<1|\ig&iz>.5) then leave;_=_*_;izz=iz;end;xx=izz;ii=ii+is*2**k;end;x=x*e()**-ii-1;z=0;_=-1;p=z;do k=1;_=-_*x;z=z+_/k;if z=p then leave;p=z;end;return z+ii
log:return ln(arg(1))/ln(10)

View file

@ -0,0 +1,36 @@
#lang racket
(define (log10 n) (/ (log n) (log 10)))
(define (first-digit n)
(quotient n (expt 10 (inexact->exact (floor (log10 n))))))
(define N 10000)
(define fibs
(let loop ([n N] [a 0] [b 1])
(if (zero? n) '() (cons b (loop (sub1 n) b (+ a b))))))
(define v (make-vector 10 0))
(for ([n fibs])
(define f (first-digit n))
(vector-set! v f (add1 (vector-ref v f))))
(printf "N OBS EXP\n")
(define (pct n) (~r (* n 100.0) #:precision 1 #:min-width 4))
(for ([i (in-range 1 10)])
(printf "~a: ~a% ~a%\n" i
(pct (/ (vector-ref v i) N))
(pct (log10 (+ 1 (/ i))))))
;; Output:
;; N OBS EXP
;; 1: 30.1% 30.1%
;; 2: 17.6% 17.6%
;; 3: 12.5% 12.5%
;; 4: 9.7% 9.7%
;; 5: 7.9% 7.9%
;; 6: 6.7% 6.7%
;; 7: 5.8% 5.8%
;; 8: 5.1% 5.1%
;; 9: 4.6% 4.6%

View file

@ -0,0 +1,37 @@
EXPECTED = (1..9).map{|d| Math.log10(1+1.0/d)}
def fib(n)
a,b = 0,1
n.times.map{ret, a, b = a, b, a+b; ret}
end
# powers of 3 as a test sequence
def power_of_threes(n)
n.times.map{|k| 3**k}
end
def heads(s)
s.map{|a| a.to_s[0].to_i}
end
def show_dist(title, s)
s = heads(s)
c = Array.new(10, 0)
s.each{|x| c[x] += 1}
size = s.size.to_f
res = (1..9).map{|d| c[d]/size}
puts "\n %s Benfords deviation" % title
res.zip(EXPECTED).each.with_index(1) do |(r, e), i|
puts "%2d: %5.1f%% %5.1f%% %5.1f%%" % [i, r*100, e*100, (r - e).abs*100]
end
end
def random(n)
n.times.map{rand(1..n)}
end
show_dist("fibbed", fib(1000))
show_dist("threes", power_of_threes(1000))
# just to show that not all kind-of-random sets behave like that
show_dist("random", random(10000))

View file

@ -0,0 +1,30 @@
N = 1000
for i = 0 to N - 1
n$ = str$(fibonacci(i))
j = val(left$(n$,1))
actual(j) = actual(j) +1
next
print
html "<table border=1><TR bgcolor=wheat><TD>Digit<td>Actual<td>Expected</td><tr>"
for i = 1 to 9
html "<tr align=right><td>";i;"</td><td>";using("##.###",actual(i)/10);"</td><td>";using("##.###", frequency(i)*100);"</td></tr>"
next
html "</table>"
end
function frequency(n)
frequency = log10(n+1) - log10(n)
end function
function log10(n)
log10 = log(n) / log(10)
end function
function fibonacci(n)
b = 1
for i = 1 to n
temp = fibonacci + b
fibonacci = b
b = temp
next i
end function

View file

@ -0,0 +1,43 @@
-- Create table
create table benford (num integer);
-- Seed table
insert into benford (num) values (1);
insert into benford (num) values (1);
insert into benford (num) values (2);
-- Populate table
insert into benford (num)
select
ult + penult
from
(select max(num) as ult from benford),
(select max(num) as penult from benford where num not in (select max(num) from benford))
-- Repeat as many times as desired
-- in Oracle SQL*Plus, press "Slash, Enter" a lot of times
-- or wrap this in a loop, but that will require something db-specific...
-- Do sums
select
digit,
count(digit) / numbers as actual,
log(10, 1 + 1 / digit) as expected
from
(
select
floor(num/power(10,length(num)-1)) as digit
from
benford
),
(
select
count(*) as numbers
from
benford
)
group by digit, numbers
order by digit;
-- Tidy up
drop table benford;

View file

@ -0,0 +1,29 @@
// Fibonacci Sequence (begining with 1,1): 1 1 2 3 5 8 13 21 34 55 ...
val fibs : Stream[BigInt] = { def series(i:BigInt,j:BigInt):Stream[BigInt] = i #:: series(j, i+j); series(1,0).tail.tail }
/**
* Given a numeric sequence, return the distribution of the most-signicant-digit
* as expected by Benford's Law and then by actual distribution.
*/
def benford[N:Numeric]( data:Seq[N] ) : Map[Int,(Double,Double)] = {
import scala.math._
val maxSize = 10000000 // An arbitrary size to avoid problems with endless streams
val size = (data.take(maxSize)).size.toDouble
val distribution = data.take(maxSize).groupBy(_.toString.head.toString.toInt).map{ case (d,l) => (d -> l.size) }
(for( i <- (1 to 9) ) yield { (i -> (log10(1D + 1D / i), (distribution(i) / size))) }).toMap
}
{
println( "Fibonacci Sequence (size=1000): 1 1 2 3 5 8 13 21 34 55 ...\n" )
println( "%9s %9s %9s".format( "Actual", "Expected", "Deviation" ) )
benford( fibs.take(1000) ).toList.sorted foreach {
case (k, v) => println( "%d: %5.2f%% | %5.2f%% | %5.4f%%".format(k,v._2*100,v._1*100,math.abs(v._2-v._1)*100) )
}
}

View file

@ -0,0 +1,19 @@
proc benfordTest {numbers} {
# Count the leading digits (RE matches first digit in each number,
# even if negative)
set accum {1 0 2 0 3 0 4 0 5 0 6 0 7 0 8 0 9 0}
foreach n $numbers {
if {[regexp {[1-9]} $n digit]} {
dict incr accum $digit
}
}
# Print the report
puts " digit | measured | theory"
puts "-------+----------+--------"
dict for {digit count} $accum {
puts [format "%6d | %7.2f%% | %5.2f%%" $digit \
[expr {$count * 100.0 / [llength $numbers]}] \
[expr {log(1+1./$digit)/log(10)*100.0}]]
}
}

View file

@ -0,0 +1,7 @@
proc fibs n {
for {set a 1;set b [set i 0]} {$i < $n} {incr i} {
lappend result [set b [expr {$a + [set a $b]}]]
}
return $result
}
benfordTest [fibs 1000]