Skip to content

Instantly share code, notes, and snippets.

@saeedvir
Created November 7, 2025 14:32
Show Gist options
  • Select an option

  • Save saeedvir/0cdaf5de7e47d679638e8dd4905c082c to your computer and use it in GitHub Desktop.

Select an option

Save saeedvir/0cdaf5de7e47d679638e8dd4905c082c to your computer and use it in GitHub Desktop.
Benford's law in php
<?php
class BenfordAnalyzer
{
protected array $data;
public function __construct(array $data)
{
$this->data = array_filter($data, function ($value) {
return is_numeric($value) && $value != 0;
});
}
protected function getFirstDigit($number): ?int
{
$number = ltrim((string) abs($number), '0.');
return $number !== '' ? (int) $number[0] : null;
}
public function actualDistribution(): array
{
$counts = array_fill(1, 9, 0);
foreach ($this->data as $value) {
$digit = $this->getFirstDigit($value);
if ($digit >= 1 && $digit <= 9) {
$counts[$digit]++;
}
}
$total = array_sum($counts);
$distribution = [];
foreach ($counts as $digit => $count) {
$distribution[$digit] = $total > 0 ? $count / $total : 0;
}
return $distribution;
}
public function benfordDistribution(): array
{
$distribution = [];
for ($d = 1; $d <= 9; $d++) {
$distribution[$d] = log10(1 + 1 / $d);
}
return $distribution;
}
public function compareDistributions(): array
{
$actual = $this->actualDistribution();
$expected = $this->benfordDistribution();
$comparison = [];
foreach ($expected as $digit => $expectedProb) {
$actualProb = $actual[$digit];
$comparison[$digit] = [
'digit' => $digit,
'expected' => round($expectedProb * 100, 2),
'actual' => round($actualProb * 100, 2),
'difference' => round(($actualProb - $expectedProb) * 100, 2),
];
}
return $comparison;
}
public function deviationScore(): float
{
$comparison = $this->compareDistributions();
$sum = 0;
foreach ($comparison as $c) {
$sum += abs($c['difference']);
}
return round($sum / 9, 2);
}
public function summaryTable(): string
{
$comparison = $this->compareDistributions();
$lines = [];
$lines[] = str_pad('رقم', 6) . str_pad('انتظار (%)', 15) . str_pad('واقعی (%)', 15) . 'اختلاف';
$lines[] = str_repeat('-', 45);
foreach ($comparison as $c) {
$lines[] =
str_pad($c['digit'], 6) .
str_pad($c['expected'], 15) .
str_pad($c['actual'], 15) .
$c['difference'];
}
$lines[] = str_repeat('-', 45);
$lines[] = 'شاخص انحراف: ' . $this->deviationScore() . '%';
return implode(PHP_EOL, $lines);
}
/**
* خروجی تحلیل به صورت JSON
*/
public function toJson(): string
{
$comparison = $this->compareDistributions();
$result = [
'distribution' => $comparison,
'deviation_score' => $this->deviationScore(),
];
return json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
}
}
@saeedvir
Copy link
Author

saeedvir commented Nov 7, 2025

How to Use ?

see online :

https://onlinephp.io/c/956b24
$data = [123, 154, 1780, 2950, 312, 45, 51, 68, 97, 1200, 18000, 1340000];

$analyzer = new BenfordAnalyzer($data);

echo $analyzer->toJson();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment