benfordgenerator

C Library and cli application to generate number sequences with first digits distributed according to Benford's Law
git clone git://git.defalsify.org/libbenford.git
Log | Files | Refs

commit dbf3c7ff51cf51ab4b2be0ec77a616bf92332a39
Author: nolash <dev@holbrook.no>
Date:   Mon, 29 May 2017 07:46:08 +0200

initial commit

Diffstat:
AMakefile | 13+++++++++++++
Asrc/Makefile | 12++++++++++++
Asrc/benford.c | 74++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/benford.o | 0
Asrc/include/benford.h | 17+++++++++++++++++
Asrc/test/Makefile | 13+++++++++++++
Asrc/test/benford_test | 0
Asrc/test/benford_test.c | 83+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
8 files changed, 212 insertions(+), 0 deletions(-)

diff --git a/Makefile b/Makefile @@ -0,0 +1,13 @@ +all: test + +dir: + mkdir -p .build + +test: libs + make -C src/test test + +libs: dir + make -C src libs + +clean: + rm -rf .build diff --git a/src/Makefile b/src/Makefile @@ -0,0 +1,12 @@ +INCLUDE = ./include/ +BUILDDIR = ../.build + +libs: + $(CC) -Wall -g -I$(INCLUDE) -o $(BUILDDIR)/benford.o -c benford.c + +#shared: + +# $(CC) -Wall -I$(INCLUDE) -o lash_tree_lib.o -fPIC -c lash_tree3.c +# $(CC) -Wall -I$(INCLUDE) -o lash_tree_dump_lib.o -fPIC -c lash_tree3_dump.c +# $(CC) -shared -Wl,-soname,liblash.so.0 -o $(SHAREDOBJECTDIR)liblash.so lash_tree_lib.o lash_tree_dump_lib.o + diff --git a/src/benford.c b/src/benford.c @@ -0,0 +1,74 @@ +#include <math.h> +#include <stdlib.h> + +#include "benford.h" + +float benford_distribution[9] = {0.16, 0.14, 0.13, 0.12, 0.11, 0.10, 0.09, 0.08, 0.07}; + +void benford_setLead_(long int* subject, int lead) { + char order; + float norm; + + order = (int)log10(*subject); + norm = (int)(*subject / (float)pow(10, order)); + *subject -= norm * pow(10, order); + *subject += lead * pow(10, order); +} + +int benford_set(benford_t* bf, long int* number) { + int lead; + + lead = benford_nextLead_(bf); + benford_setLead_(number, lead + 1); + + return 0; +} + +int benford_nextLead_(benford_t* bf) { + int i; + float ratio; + + for (i = 0; i < 9; i++) { + + ratio = bf->counts[i] / (bf->total + 1.f); + if (ratio < benford_distribution[i]) { + bf->counts[i]++; + bf->total++; + return i; + } + } + + return -1; +} + +/** + * \fn benford_t* benford_new() + * \brief Constructs a new benford number distribution generator + */ +benford_t* benford_new() { + benford_t* bf; + int i; + + bf = malloc(sizeof(benford_t)); + + if (bf == NULL) { + return 0; + } + for (i = 0; i < 9; i++) { + bf->counts[i] = 0; + } + + bf->total = 0; + + return bf; +} + +/** + * \fn benford_t* benford_free() + * \brief Free up resources from distribution generator + */ +void benford_free(benford_t* bf) { + if (bf != NULL) { + free(bf); + } +} diff --git a/src/benford.o b/src/benford.o Binary files differ. diff --git a/src/include/benford.h b/src/include/benford.h @@ -0,0 +1,17 @@ +#ifndef BENFORD_H_ +#define BENFORD_H_ + +typedef struct benford { + char counts[9]; + int total; +} benford_t; + +benford_t* benford_new(); +void benford_free(benford_t* bf); +int benford_set(benford_t* bf, long int* number); + +// private functions +void benford_setLead_(long int* subject, int lead); +int benford_nextLead_(benford_t* bf); + +#endif // BENFORD_H_ diff --git a/src/test/Makefile b/src/test/Makefile @@ -0,0 +1,13 @@ +INCLUDE = ../include/ +BUILDDIR = ../../.build + +test: + $(CC) -Wall -g -I$(INCLUDE) -o $(BUILDDIR)/benford_test.o -c benford_test.c + $(CC) -Wall -o benford_test $(BUILDDIR)/benford.o $(BUILDDIR)/benford_test.o -lm + +#shared: + +# $(CC) -Wall -I$(INCLUDE) -o lash_tree_lib.o -fPIC -c lash_tree3.c +# $(CC) -Wall -I$(INCLUDE) -o lash_tree_dump_lib.o -fPIC -c lash_tree3_dump.c +# $(CC) -shared -Wl,-soname,liblash.so.0 -o $(SHAREDOBJECTDIR)liblash.so lash_tree_lib.o lash_tree_dump_lib.o + diff --git a/src/test/benford_test b/src/test/benford_test Binary files differ. diff --git a/src/test/benford_test.c b/src/test/benford_test.c @@ -0,0 +1,83 @@ +#include <stdio.h> +#include <stdlib.h> +#include <time.h> + +#include "benford.h" + +#define TESTCOUNT 100 + +int setLead() { + long int t = 123456; + int d = 4; + benford_setLead_(&t, d); + + if (t != 323456) { + return -1; + } + + return 0; +} + +void getSequence(char *leads, int count) { + int i; + benford_t* bf = benford_new(); + for (i = 0; i < count; i++) { + *(leads+i) = benford_nextLead_(bf); + } + benford_free(bf); +} + +int getLeads(int count) { + int i; + char *res = calloc(sizeof(int), count); + int *rescount = calloc(sizeof(int), 9); + + getSequence(res, count); + + for (i = 0; i < count; i++) { + (*(rescount + (*(res+i))))++; + } + for (i = 0; i < 9; i++) { + printf("%i: %i\n", i, *(rescount+i)); + } + return 0; +} + +int getNumbers(int count) { + int i; + + long int min = 123; + long int max = 912346789; + + char* leads = malloc(sizeof(char) * count); + getSequence(leads, count); + + benford_t* bf = benford_new(); + + for (i = 0; i < TESTCOUNT; i++) { + long int n = (rand() % (max - min)) + min + 1; + long int r = n; + benford_set(bf, &r); + printf("%i: [%i?] %li -> %li\n", i, *(leads+i) + 1, n, r); + } + + benford_free(bf); + return 0; +} + +int main() { + int e; + + srand(clock()); + + if ((e = setLead()) > 0) { + return e; + } + if ((e = getLeads(TESTCOUNT)) > 0) { + return e; + } + if ((e = getNumbers(TESTCOUNT)) > 0) { + return e; + } + return 0; +}