Distribution of 0 digits in factorial series: Difference between revisions

Add C# implementation
No edit summary
(Add C# implementation)
 
(35 intermediate revisions by 15 users not shown)
Line 1:
{{draft task|Mathematics}}
 
Large Factorials and the Distribution of '0' in base 10 digits.
Line 41:
permanently falls below 0.16. This task took many hours in the Python example, though I wonder if there is a faster
algorithm out there.
=={{header|11l}}==
{{trans|Python}}
 
<syntaxhighlight lang="11l">F facpropzeros(n, verbose = 1B)
V proportions = [0.0] * n
V (fac, psum) = (BigInt(1), 0.0)
L(i) 0 .< n
fac *= i + 1
V d = String(fac)
psum += sum(d.map(x -> Int(x == ‘0’))) / Float(d.len)
proportions[i] = psum / (i + 1)
 
I verbose
print(‘The mean proportion of 0 in factorials from 1 to #. is #..’.format(n, psum / n))
 
R proportions
 
L(n) [100, 1000, 10000]
facpropzeros(n)</syntaxhighlight>
 
{{out}}
<pre>
The mean proportion of 0 in factorials from 1 to 100 is 0.246753186.
The mean proportion of 0 in factorials from 1 to 1000 is 0.203544551.
The mean proportion of 0 in factorials from 1 to 10000 is 0.173003848.
</pre>
 
=== Base 1000 version ===
<syntaxhighlight lang="11l">F zinit()
V zc = [0] * 999
L(x) 1..9
zc[x - 1] = 2
zc[10 * x - 1] = 2
zc[100 * x - 1] = 2
L(y) (10.<100).step(10)
zc[y + x - 1] = 1
zc[10 * y + x - 1] = 1
zc[10 * (y + x) - 1] = 1
 
R zc
 
F meanfactorialdigits()
V zc = zinit()
V rfs = [1]
V (total, trail, first) = (0.0, 1, 0)
L(f) 2 .< 50000
V (carry, d999, zeroes) = (0, 0, (trail - 1) * 3)
V (j, l) = (trail, rfs.len)
L j <= l | carry != 0
I j <= l
carry = rfs[j - 1] * f + carry
 
d999 = carry % 1000
I j <= l
rfs[j - 1] = d999
E
rfs.append(d999)
 
zeroes += I d999 == 0 {3} E zc[d999 - 1]
carry I/= 1000
j++
 
L rfs[trail - 1] == 0
trail++
 
d999 = rfs.last
d999 = I d999 >= 100 {0} E I d999 < 10 {2} E 1
 
zeroes -= d999
V digits = rfs.len * 3 - d999
total += Float(zeroes) / digits
V ratio = total / f
I f C [100, 1000, 10000]
print(‘The mean proportion of zero digits in factorials to #. is #.’.format(f, ratio))
 
I ratio >= 0.16
first = 0
E I first == 0
first = f
 
print(‘The mean proportion dips permanently below 0.16 at ’first‘.’)
 
meanfactorialdigits()</syntaxhighlight>
 
{{out}}
<pre>
The mean proportion of zero digits in factorials to 100 is 0.246753186
The mean proportion of zero digits in factorials to 1000 is 0.203544551
The mean proportion of zero digits in factorials to 10000 is 0.173003848
The mean proportion dips permanently below 0.16 at 47332.
</pre>
=={{header|Arturo}}==
<syntaxhighlight lang="arturo">su: 0.0
f: 1
lim: 100
loop 1..10000 'n [
'f * n
str: to :string f
'su + (enumerate str 'c -> c = `0`) // size str
if n = lim [
print [n ":" su // n]
'lim * 10
]
]</syntaxhighlight>
 
{{out}}
 
<pre>100 : 0.2467531861674322
1000 : 0.2035445511031646
10000 : 0.1730038482418671</pre>
 
=={{header|C#}}==
{{trans|Java}}
<syntaxhighlight lang="C#">
using System;
using System.Collections.Generic;
using System.Numerics;
 
public class DistributionInFactorials
{
public static void Main(string[] args)
{
List<int> limits = new List<int> { 100, 1_000, 10_000 };
foreach (int limit in limits)
{
MeanFactorialDigits(limit);
}
}
 
private static void MeanFactorialDigits(int limit)
{
BigInteger factorial = BigInteger.One;
double proportionSum = 0.0;
double proportionMean = 0.0;
 
for (int n = 1; n <= limit; n++)
{
factorial = factorial * n;
string factorialString = factorial.ToString();
int digitCount = factorialString.Length;
long zeroCount = factorialString.Split('0').Length - 1;
proportionSum += (double)zeroCount / digitCount;
proportionMean = proportionSum / n;
}
 
string result = string.Format("{0:F8}", proportionMean);
Console.WriteLine("Mean proportion of zero digits in factorials from 1 to " + limit + " is " + result);
}
}
</syntaxhighlight>
{{out}}
<pre>
Mean proportion of zero digits in factorials from 1 to 100 is 0.24675319
Mean proportion of zero digits in factorials from 1 to 1000 is 0.20354455
Mean proportion of zero digits in factorials from 1 to 10000 is 0.17300385
</pre>
 
=={{header|C++}}==
{{trans|Phix}}
<syntaxhighlight lang="cpp">#include <array>
#include <chrono>
#include <iomanip>
#include <iostream>
#include <vector>
 
auto init_zc() {
std::array<int, 1000> zc;
zc.fill(0);
zc[0] = 3;
for (int x = 1; x <= 9; ++x) {
zc[x] = 2;
zc[10 * x] = 2;
zc[100 * x] = 2;
for (int y = 10; y <= 90; y += 10) {
zc[y + x] = 1;
zc[10 * y + x] = 1;
zc[10 * (y + x)] = 1;
}
}
return zc;
}
 
template <typename clock_type>
auto elapsed(const std::chrono::time_point<clock_type>& t0) {
auto t1 = clock_type::now();
auto duration =
std::chrono::duration_cast<std::chrono::milliseconds>(t1 - t0);
return duration.count();
}
 
int main() {
auto zc = init_zc();
auto t0 = std::chrono::high_resolution_clock::now();
int trail = 1, first = 0;
double total = 0;
std::vector<int> rfs{1};
std::cout << std::fixed << std::setprecision(10);
for (int f = 2; f <= 50000; ++f) {
int carry = 0, d999, zeroes = (trail - 1) * 3, len = rfs.size();
for (int j = trail - 1; j < len || carry != 0; ++j) {
if (j < len)
carry += rfs[j] * f;
d999 = carry % 1000;
if (j < len)
rfs[j] = d999;
else
rfs.push_back(d999);
zeroes += zc[d999];
carry /= 1000;
}
while (rfs[trail - 1] == 0)
++trail;
d999 = rfs.back();
d999 = d999 < 100 ? (d999 < 10 ? 2 : 1) : 0;
zeroes -= d999;
int digits = rfs.size() * 3 - d999;
total += double(zeroes) / digits;
double ratio = total / f;
if (ratio >= 0.16)
first = 0;
else if (first == 0)
first = f;
if (f == 100 || f == 1000 || f == 10000) {
std::cout << "Mean proportion of zero digits in factorials to " << f
<< " is " << ratio << ". (" << elapsed(t0) << "ms)\n";
}
}
std::cout << "The mean proportion dips permanently below 0.16 at " << first
<< ". (" << elapsed(t0) << "ms)\n";
}</syntaxhighlight>
 
{{out}}
<pre>
Mean proportion of zero digits in factorials to 100 is 0.2467531862. (0ms)
Mean proportion of zero digits in factorials to 1000 is 0.2035445511. (1ms)
Mean proportion of zero digits in factorials to 10000 is 0.1730038482. (152ms)
The mean proportion dips permanently below 0.16 at 47332. (4598ms)
</pre>
 
=={{header|Go}}==
===Brute force===
{{libheader|GMP(Go wrapper)}}
{{libheader|Go-rcu}}
Timings here are 2.8 seconds for the basic task and 182.5 seconds for the stretch goal.
Brute force as I'll be surprised if there is a faster 'exact' algorithm for this task.
<syntaxhighlight lang="go">package main
 
However, the combination of a native code compiler and GMP really cuts down the times (2.8 seconds for the basic task and 182.5 seconds for the stretch goal). Expect these times to be reduced further by the fastest languages.
<lang go>package main
 
import (
Line 87 ⟶ 324:
fmt.Printf("%6s = %12.10f", rcu.Commatize(int(first)), firstRatio)
fmt.Println(" (stays below 0.16 after this)")
fmt.PrintlnPrintf("%6s = %12.10f\n", "50,000", sum / 50000)
}</langsyntaxhighlight>
 
{{out}}
Line 97 ⟶ 334:
10,000 = 0.1730038482
47,332 = 0.1599999958 (stays below 0.16 after this)
50,000 = 0.1596200546
</pre>
<br>
==='String math' and base 1000===
{{trans|Phix}}
Much quicker than before with 10,000 now being reached in 0.35 seconds and the stretch goal in about 5.5 seconds.
<syntaxhighlight lang="go">package main
 
import (
"fmt"
"rcu"
)
 
var rfs = []int{1} // reverse factorial(1) in base 1000
var zc = make([]int, 999)
 
func init() {
for x := 1; x <= 9; x++ {
zc[x-1] = 2 // 00x
zc[10*x-1] = 2 // 0x0
zc[100*x-1] = 2 // x00
var y = 10
for y <= 90 {
zc[y+x-1] = 1 // 0yx
zc[10*y+x-1] = 1 // y0x
zc[10*(y+x)-1] = 1 // yx0
y += 10
}
}
}
 
func main() {
total := 0.0
trail := 1
first := 0
firstRatio := 0.0
fmt.Println("The mean proportion of zero digits in factorials up to the following are:")
for f := 2; f <= 10000; f++ {
carry := 0
d999 := 0
zeros := (trail - 1) * 3
j := trail
l := len(rfs)
for j <= l || carry != 0 {
if j <= l {
carry = rfs[j-1]*f + carry
}
d999 = carry % 1000
if j <= l {
rfs[j-1] = d999
} else {
rfs = append(rfs, d999)
}
if d999 == 0 {
zeros += 3
} else {
zeros += zc[d999-1]
}
carry /= 1000
j++
}
for rfs[trail-1] == 0 {
trail++
}
// d999 = quick correction for length and zeros
d999 = rfs[len(rfs)-1]
if d999 < 100 {
if d999 < 10 {
d999 = 2
} else {
d999 = 1
}
} else {
d999 = 0
}
zeros -= d999
digits := len(rfs)*3 - d999
total += float64(zeros) / float64(digits)
ratio := total / float64(f)
if ratio >= 0.16 {
first = 0
firstRatio = 0.0
} else if first == 0 {
first = f
firstRatio = ratio
}
if f == 100 || f == 1000 || f == 10000 {
fmt.Printf("%6s = %12.10f\n", rcu.Commatize(f), ratio)
}
}
fmt.Printf("%6s = %12.10f", rcu.Commatize(first), firstRatio)
fmt.Println(" (stays below 0.16 after this)")
fmt.Printf("%6s = %12.10f\n", "50,000", total/50000)
}</syntaxhighlight>
 
{{out}}
<pre>
Same as 'brute force' version.
</pre>
 
=={{header|Java}}==
<syntaxhighlight lang="java">
 
import java.math.BigInteger;
import java.util.List;
 
public final class DistributionInFactorials {
 
public static void main(String[] aArgs) {
List<Integer> limits = List.of( 100, 1_000, 10_000 );
for ( Integer limit : limits ) {
meanFactorialDigits(limit);
}
}
private static void meanFactorialDigits(Integer aLimit) {
BigInteger factorial = BigInteger.ONE;
double proportionSum = 0.0;
double proportionMean = 0.0;
for ( int n = 1; n <= aLimit; n++ ) {
factorial = factorial.multiply(BigInteger.valueOf(n));
String factorialString = factorial.toString();
int digitCount = factorialString.length();
long zeroCount = factorialString.chars().filter( ch -> ch == '0' ).count();
proportionSum += (double) zeroCount / digitCount;
proportionMean = proportionSum / n;
}
String result = String.format("%.8f", proportionMean);
System.out.println("Mean proportion of zero digits in factorials from 1 to " + aLimit + " is " + result);
}
 
}
</syntaxhighlight>
{{ out }}
<pre>
Mean proportion of zero digits in factorials from 1 to 100 is 0.24675319
Mean proportion of zero digits in factorials from 1 to 1000 is 0.20354455
Mean proportion of zero digits in factorials from 1 to 10000 is 0.17300385
</pre>
 
=={{header|jq}}==
'''Works with jq'''
 
The precision of jq's integer arithmetic is not up to this task, so in the following we borrow from the "BigInt" library and use a string representation of integers.
 
Unfortunately, although gojq (the Go implementation of jq) does support unbounded-precision integer arithmetic, it is unsuited for the task because of memory management issues.
 
'''From BigInt.jq'''
<syntaxhighlight lang="jq">
# multiply two decimal strings, which may be signed (+ or -)
def long_multiply(num1; num2):
 
def stripsign:
.[0:1] as $a
| if $a == "-" then [ -1, .[1:]]
elif $a == "+" then [ 1, .[1:]]
else [1, .]
end;
 
def adjustsign(sign):
if sign == 1 then . else "-" + . end;
 
# mult/2 assumes neither argument has a sign
def mult(num1;num2):
(num1 | explode | map(.-48) | reverse) as $a1
| (num2 | explode | map(.-48) | reverse) as $a2
| reduce range(0; num1|length) as $i1
([]; # result
reduce range(0; num2|length) as $i2
(.;
($i1 + $i2) as $ix
| ( $a1[$i1] * $a2[$i2] + (if $ix >= length then 0 else .[$ix] end) ) as $r
| if $r > 9 # carrying
then
.[$ix + 1] = ($r / 10 | floor) + (if $ix + 1 >= length then 0 else .[$ix + 1] end )
| .[$ix] = $r - ( $r / 10 | floor ) * 10
else
.[$ix] = $r
end
)
)
| reverse | map(.+48) | implode;
 
(num1|stripsign) as $a1
| (num2|stripsign) as $a2
| if $a1[1] == "0" or $a2[1] == "0" then "0"
elif $a1[1] == "1" then $a2[1]|adjustsign( $a1[0] * $a2[0] )
elif $a2[1] == "1" then $a1[1]|adjustsign( $a1[0] * $a2[0] )
else mult($a1[1]; $a2[1]) | adjustsign( $a1[0] * $a2[0] )
end;
</syntaxhighlight>
'''The task'''
<syntaxhighlight lang="jq">
def count(s): reduce s as $x (0; .+1);
 
def meanfactorialdigits:
def digits: tostring | explode;
def nzeros: count( .[] | select(. == 48) ); # "0" is 48
. as $N
| 0.16 as $goal
| label $out
| reduce range( 1; 1+$N ) as $i ( {factorial: "1", proportionsum: 0.0, first: null };
.factorial = long_multiply(.factorial; $i|tostring)
| (.factorial|digits) as $d
| .proportionsum += ($d | (nzeros / length))
| (.proportionsum / $i) as $propmean
| if .first
then if $propmean > $goal then .first = null else . end
elif $propmean <= $goal then .first = $i
else .
end)
| "Mean proportion of zero digits in factorials to \($N) is \(.proportionsum/$N);" +
(if .first then " mean <= \($goal) from N=\(.first) on." else " goal (\($goal)) unmet." end);
 
# The task:
100, 1000, 10000 | meanfactorialdigits</syntaxhighlight>
{{out}}
<pre>
Mean proportion of zero digits in factorials to 100 is 0.24675318616743216; goal (0.16) unmet.
Mean proportion of zero digits in factorials to 1000 is 0.20354455110316458; goal (0.16) unmet.
Mean proportion of zero digits in factorials to 10000 is 0.17300384824186707; goal (0.16) unmet.
</pre>
=={{header|Julia}}==
<langsyntaxhighlight lang="julia">function meanfactorialdigits(N, goal = 0.0)
factoril, proportionsum = big"1", 0.0
for i in 1:N
Line 121 ⟶ 581:
 
@time meanfactorialdigits(50000, 0.16)
</langsyntaxhighlight>{{out}}
<pre>
Mean proportion of zero digits in factorials to 100 is 0.24675318616743216
Line 131 ⟶ 591:
</pre>
 
=== Base 1000 version ===
{{trans|Pascal, Phix}}
<syntaxhighlight lang="julia">function init_zc()
zc = zeros(Int, 999)
for x in 1:9
zc[x] = 2 # 00x
zc[10*x] = 2 # 0x0
zc[100*x] = 2 # x00
for y in 10:10:90
zc[y+x] = 1 # 0yx
zc[10*y+x] = 1 # y0x
zc[10*(y+x)] = 1 # yx0
end
end
return zc
end
 
function meanfactorialzeros(N = 50000, verbose = true)
zc = init_zc()
rfs = [1]
 
total, trail, first, firstratio = 0.0, 1, 0, 0.0
 
for f in 2:N
carry, d999, zeroes = 0, 0, (trail - 1) * 3
j, l = trail, length(rfs)
while j <= l || carry != 0
if j <= l
carry = (rfs[j]) * f + carry
end
d999 = carry % 1000
if j <= l
rfs[j] = d999
else
push!(rfs, d999)
end
zeroes += (d999 == 0) ? 3 : zc[d999]
carry ÷= 1000
j += 1
end
while rfs[trail] == 0
trail += 1
end
# d999 = quick correction for length and zeroes:
d999 = rfs[end]
d999 = d999 < 100 ? d999 < 10 ? 2 : 1 : 0
zeroes -= d999
digits = length(rfs) * 3 - d999
total += zeroes / digits
ratio = total / f
if ratio >= 0.16
first = 0
firstratio = 0.0
elseif first == 0
first = f
firstratio = ratio
end
if f in [100, 1000, 10000]
verbose && println("Mean proportion of zero digits in factorials to $f is $ratio")
end
end
verbose && println("The mean proportion dips permanently below 0.16 at $first.")
end
 
meanfactorialzeros(100, false)
@time meanfactorialzeros()
</syntaxhighlight>{{out}}
<pre>
Mean proportion of zero digits in factorials to 100 is 0.24675318616743216
Mean proportion of zero digits in factorials to 1000 is 0.20354455110316458
Mean proportion of zero digits in factorials to 10000 is 0.17300384824186707
The mean proportion dips permanently below 0.16 at 47332.
4.638323 seconds (50.08 k allocations: 7.352 MiB)
</pre>
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<syntaxhighlight lang="mathematica">ClearAll[ZeroDigitsFractionFactorial]
ZeroDigitsFractionFactorial[n_Integer] := Module[{m},
m = IntegerDigits[n!];
Count[m, 0]/Length[m]
]
ZeroDigitsFractionFactorial /@ Range[6] // Mean // N
ZeroDigitsFractionFactorial /@ Range[25] // Mean // N
ZeroDigitsFractionFactorial /@ Range[100] // Mean // N
ZeroDigitsFractionFactorial /@ Range[1000] // Mean // N
ZeroDigitsFractionFactorial /@ Range[10000] // Mean // N
 
fracs = ParallelMap[ZeroDigitsFractionFactorial, Range[50000], Method -> ("ItemsPerEvaluation" -> 100)];
means = Accumulate[N@fracs]/Range[Length[fracs]];
len = LengthWhile[Reverse@means, # < 0.16 &];
50000 - len + 1</syntaxhighlight>
{{out}}
<pre>0.111111
0.267873
0.246753
0.203545
0.173004
47332</pre>
=={{header|Nim}}==
 
===Task===
{{libheader|bignum}}
<langsyntaxhighlight Nimlang="nim">import strutils, std/monotimes
import bignum
 
Line 150 ⟶ 707:
lim *= 10
echo()
echo getMonoTime() - t0</langsyntaxhighlight>
 
{{out}}
Line 163 ⟶ 720:
At each step, we eliminate the trailing zeroes to reduce the length of the number and save some time. But this is not much, about 8%.
 
<langsyntaxhighlight Nimlang="nim">import strutils, std/monotimes
import bignum
 
Line 184 ⟶ 741:
 
echo "Permanently below 0.16 at n = ", first
echo "Execution time: ", getMonoTime() - t0</langsyntaxhighlight>
 
{{out}}
<pre>Permanently below 0.16 at n = 47332
Execution time: (seconds: 190, nanosecond: 215845101)</pre>
=={{header|Pascal}}==
Doing the calculation in Base 1,000,000,000 like in [[Primorial_numbers#alternative]].<BR>
The most time consuming is converting to string and search for zeros.<BR>
Therefor I do not convert to string.I divide the base in sections of 3 digits with counting zeros in a lookup table.
<syntaxhighlight lang="pascal">program Factorial;
{$IFDEF FPC} {$MODE DELPHI} {$Optimization ON,ALL} {$ENDIF}
uses
sysutils;
type
tMul = array of LongWord;
tpMul = pLongWord;
const
LongWordDec = 1000*1000*1000;
LIMIT = 50000;
var
CountOfZero : array[0..999] of byte;
SumOfRatio :array[0..LIMIT] of extended;
 
 
procedure OutMul(pMul:tpMul;Lmt :NativeInt);
// for testing
Begin
write(pMul[lmt]);
For lmt := lmt-1 downto 0 do
write(Format('%.9d',[pMul[lmt]]));
writeln;
end;
 
procedure InitCoZ;
//Init Lookup table for 3 digits
var
x,y : integer;
begin
fillchar(CountOfZero,SizeOf(CountOfZero),#0);
CountOfZero[0] := 3; //000
For x := 1 to 9 do
Begin
CountOfZero[x] := 2; //00x
CountOfZero[10*x] := 2; //0x0
CountOfZero[100*x] := 2; //x00
y := 10;
repeat
CountOfZero[y+x] := 1; //0yx
CountOfZero[10*y+x] := 1; //y0x
CountOfZero[10*(y+x)] := 1; //yx0
inc(y,10)
until y > 100;
end;
end;
 
function getFactorialDecDigits(n:NativeInt):NativeInt;
var
res: extended;
Begin
result := -1;
IF (n > 0) AND (n <= 1000*1000) then
Begin
res := 0;
repeat res := res+ln(n); dec(n); until n < 2;
result := trunc(res/ln(10))+1;
end;
end;
 
function CntZero(pMul:tpMul;Lmt :NativeInt):NativeUint;
//count zeros in Base 1,000,000,000 number
var
q,r : LongWord;
i : NativeInt;
begin
result := 0;
For i := Lmt-1 downto 0 do
Begin
q := pMul[i];
r := q DIV 1000;
result +=CountOfZero[q-1000*r];//q-1000*r == q mod 1000
q := r;
r := q DIV 1000;
result +=CountOfZero[q-1000*r];
q := r;
r := q DIV 1000;
result +=CountOfZero[q-1000*r];
end;
//special case first digits no leading '0'
q := pMul[lmt];
while q >= 1000 do
begin
r := q DIV 1000;
result +=CountOfZero[q-1000*r];
q := r;
end;
while q > 0 do
begin
r := q DIV 10;
result += Ord( q-10*r= 0);
q := r;
end;
end;
 
function GetCoD(pMul:tpMul;Lmt :NativeInt):NativeUint;
//count of decimal digits
var
i : longWord;
begin
result := 9*Lmt;
i := pMul[Lmt];
while i > 1000 do
begin
i := i DIV 1000;
inc(result,3);
end;
while i > 0 do
begin
i := i DIV 10;
inc(result);
end;
end;
 
procedure DoChecks(pMul:tpMul;Lmt,i :NativeInt);
//(extended(1.0)* makes TIO.RUN faster // only using FPU?
Begin
SumOfRatio[i] := SumOfRatio[i-1] + (extended(1.0)*CntZero(pMul,Lmt))/GetCoD(pMul,Lmt);
end;
 
function MulByI(pMul:tpMul;UL,i :NativeInt):NativeInt;
var
prod : Uint64;
j : nativeInt;
carry : LongWord;
begin
result := UL;
carry := 0;
For j := 0 to result do
Begin
prod := i*pMul[0]+Carry;
Carry := prod Div LongWordDec;
pMul[0] := Prod - LongWordDec*Carry;
inc(pMul);
end;
 
IF Carry <> 0 then
Begin
inc(result);
pMul[0]:= Carry;
End;
end;
 
procedure getFactorialExact(n:NativeInt);
var
MulArr : tMul;
pMul : tpMul;
i,ul : NativeInt;
begin
i := getFactorialDecDigits(n) DIV 9 +10;
Setlength(MulArr,i);
pMul := @MulArr[0];
Ul := 0;
pMul[Ul]:= 1;
i := 1;
repeat
UL := MulByI(pMul,UL,i);
//Now do what you like to do with i!
DoChecks(pMul,UL,i);
inc(i);
until i> n;
end;
 
procedure Out_(i: integer);
begin
if i > LIMIT then
EXIT;
writeln(i:8,SumOfRatio[i]/i:18:15);
end;
 
var
i : integer;
Begin
InitCoZ;
SumOfRatio[0]:= 0;
getFactorialExact(LIMIT);
Out_(100);
Out_(1000);
Out_(10000);
Out_(50000);
i := limit;
while i >0 do
Begin
if SumOfRatio[i]/i >0.16 then
break;
dec(i);
end;
inc(i);
writeln('First ratio < 0.16 ', i:8,SumOfRatio[i]/i:20:17);
end.</syntaxhighlight>
{{out}}
<pre> 100 0.246753186167432
1000 0.203544551103165
10000 0.173003848241866
50000 0.159620054602269
First ratio < 0.16 47332 0.15999999579985665
Real time: 4.898 s CPU share: 99.55 % // 2.67s on 2200G freepascal 3.2.2</pre>
=={{header|Perl}}==
{{libheader|ntheory}}
<syntaxhighlight lang="perl">use strict;
use warnings;
use ntheory qw/factorial/;
 
for my $n (100, 1000, 10000) {
my($sum,$f) = 0;
$f = factorial $_ and $sum += ($f =~ tr/0//) / length $f for 1..$n;
printf "%5d: %.5f\n", $n, $sum/$n;
}</syntaxhighlight>
{{out}}
<pre> 100: 0.24675
1000: 0.20354
10000: 0.17300</pre>
=={{header|Phix}}==
Using "string math" to create reversed factorials, for slightly easier skipping of "trailing" zeroes,
but converted to base 1000 and with the zero counting idea from Pascal, which sped it up threefold.
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">rfs</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">}</span> <span style="color: #000080;font-style:italic;">-- reverse factorial(1) in base 1000</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">init_zc</span><span style="color: #0000FF;">()</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">zc</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">999</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">9</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">zc</span><span style="color: #0000FF;">[</span><span style="color: #000000;">x</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">2</span> <span style="color: #000080;font-style:italic;">-- 00x</span>
<span style="color: #000000;">zc</span><span style="color: #0000FF;">[</span><span style="color: #000000;">10</span><span style="color: #0000FF;">*</span><span style="color: #000000;">x</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">2</span> <span style="color: #000080;font-style:italic;">-- 0x0</span>
<span style="color: #000000;">zc</span><span style="color: #0000FF;">[</span><span style="color: #000000;">100</span><span style="color: #0000FF;">*</span><span style="color: #000000;">x</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">2</span> <span style="color: #000080;font-style:italic;">-- x00</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">=</span><span style="color: #000000;">10</span> <span style="color: #008080;">to</span> <span style="color: #000000;">90</span> <span style="color: #008080;">by</span> <span style="color: #000000;">10</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">zc</span><span style="color: #0000FF;">[</span><span style="color: #000000;">y</span><span style="color: #0000FF;">+</span><span style="color: #000000;">x</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span> <span style="color: #000080;font-style:italic;">-- 0yx</span>
<span style="color: #000000;">zc</span><span style="color: #0000FF;">[</span><span style="color: #000000;">10</span><span style="color: #0000FF;">*</span><span style="color: #000000;">y</span><span style="color: #0000FF;">+</span><span style="color: #000000;">x</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span> <span style="color: #000080;font-style:italic;">-- y0x</span>
<span style="color: #000000;">zc</span><span style="color: #0000FF;">[</span><span style="color: #000000;">10</span><span style="color: #0000FF;">*(</span><span style="color: #000000;">y</span><span style="color: #0000FF;">+</span><span style="color: #000000;">x</span><span style="color: #0000FF;">)]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span> <span style="color: #000080;font-style:italic;">-- yx0</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">zc</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">zc</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">init_zc</span><span style="color: #0000FF;">()</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">t0</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">(),</span>
<span style="color: #000000;">total</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">trail</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">first</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">f</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span> <span style="color: #008080;">to</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()=</span><span style="color: #004600;">JS</span><span style="color: #0000FF;">?</span><span style="color: #000000;">10000</span><span style="color: #0000FF;">:</span><span style="color: #000000;">50000</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">carry</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">d999</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">zeroes</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">trail</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)*</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">j</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">trail</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">l</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rfs</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">while</span> <span style="color: #000000;">j</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">l</span> <span style="color: #008080;">or</span> <span style="color: #000000;">carry</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">j</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">l</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">carry</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">rfs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">])*</span><span style="color: #000000;">f</span><span style="color: #0000FF;">+</span><span style="color: #000000;">carry</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">d999</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">remainder</span><span style="color: #0000FF;">(</span><span style="color: #000000;">carry</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1000</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">j</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">l</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">rfs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">d999</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">rfs</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">d999</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">zeroes</span> <span style="color: #0000FF;">+=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">d999</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span><span style="color: #0000FF;">?</span><span style="color: #000000;">3</span><span style="color: #0000FF;">:</span><span style="color: #000000;">zc</span><span style="color: #0000FF;">[</span><span style="color: #000000;">d999</span><span style="color: #0000FF;">])</span>
<span style="color: #000000;">carry</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">carry</span><span style="color: #0000FF;">/</span><span style="color: #000000;">1000</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">j</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #008080;">while</span> <span style="color: #000000;">rfs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">trail</span><span style="color: #0000FF;">]=</span><span style="color: #000000;">0</span> <span style="color: #008080;">do</span> <span style="color: #000000;">trail</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span> <span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #000080;font-style:italic;">-- d999 := quick correction for length and zeroes:</span>
<span style="color: #000000;">d999</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">rfs</span><span style="color: #0000FF;">[$]</span>
<span style="color: #000000;">d999</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">d999</span><span style="color: #0000FF;"><</span><span style="color: #000000;">100</span><span style="color: #0000FF;">?</span><span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">d999</span><span style="color: #0000FF;"><</span><span style="color: #000000;">10</span><span style="color: #0000FF;">?</span><span style="color: #000000;">2</span><span style="color: #0000FF;">:</span><span style="color: #000000;">1</span><span style="color: #0000FF;">):</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">zeroes</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">d999</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">digits</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rfs</span><span style="color: #0000FF;">)*</span><span style="color: #000000;">3</span><span style="color: #0000FF;">-</span><span style="color: #000000;">d999</span>
<span style="color: #000000;">total</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">zeroes</span><span style="color: #0000FF;">/</span><span style="color: #000000;">digits</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">ratio</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">total</span><span style="color: #0000FF;">/</span><span style="color: #000000;">f</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">ratio</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">0.16</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">first</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">elsif</span> <span style="color: #000000;">first</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">first</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">f</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">f</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">100</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1000</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10000</span><span style="color: #0000FF;">})</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">e</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">elapsed</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">time</span><span style="color: #0000FF;">()-</span><span style="color: #000000;">t0</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Mean proportion of zero digits in factorials to %d is %.10f (%s)\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">f</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ratio</span><span style="color: #0000FF;">,</span><span style="color: #000000;">e</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()!=</span><span style="color: #004600;">JS</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">e</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">elapsed</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">time</span><span style="color: #0000FF;">()-</span><span style="color: #000000;">t0</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"The mean proportion dips permanently below 0.16 at %d. (%s)\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">first</span><span style="color: #0000FF;">,</span><span style="color: #000000;">e</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Mean proportion of zero digits in factorials to 100 is 0.2467531862 (0s)
Mean proportion of zero digits in factorials to 1000 is 0.2035445511 (0.2s)
Mean proportion of zero digits in factorials to 10000 is 0.1730038482 (2.3s)
The mean proportion dips permanently below 0.16 at 47332. (1 minute and 2s)
</pre>
<small>(stretch goal removed under pwa/p2js since otherwise you'd get a blank screen for 2 or 3 minutes)</small>
=== trailing zeroes only ===
Should you only be interested in the ratio of trailing zeroes, you can do that much faster:
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">t0</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">(),</span>
<span style="color: #000000;">f10</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">log10</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">total</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">first</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">f</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span> <span style="color: #008080;">to</span> <span style="color: #000000;">50000</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">f10</span> <span style="color: #0000FF;">+=</span> <span style="color: #7060A8;">log10</span><span style="color: #0000FF;">(</span><span style="color: #000000;">f</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">digits</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">ceil</span><span style="color: #0000FF;">(</span><span style="color: #000000;">f10</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">zeroes</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">v</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">5</span>
<span style="color: #008080;">while</span> <span style="color: #000000;">v</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">f</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">zeroes</span> <span style="color: #0000FF;">+=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">f</span><span style="color: #0000FF;">/</span><span style="color: #000000;">v</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">v</span> <span style="color: #0000FF;">*=</span> <span style="color: #000000;">5</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #000000;">total</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">zeroes</span><span style="color: #0000FF;">/</span><span style="color: #000000;">digits</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">ratio</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">total</span><span style="color: #0000FF;">/</span><span style="color: #000000;">f</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">ratio</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">0.07</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">first</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">elsif</span> <span style="color: #000000;">first</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">first</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">f</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">f</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">100</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1000</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10000</span><span style="color: #0000FF;">})</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Mean proportion of trailing zeroes in factorials to %d is %f\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">f</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ratio</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">e</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">elapsed</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">time</span><span style="color: #0000FF;">()-</span><span style="color: #000000;">t0</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"The mean proportion dips permanently below 0.07 at %d. (%s)\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">first</span><span style="color: #0000FF;">,</span><span style="color: #000000;">e</span><span style="color: #0000FF;">})</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Mean proportion of trailing zeroes in factorials to 100 is 0.170338
Mean proportion of trailing zeroes in factorials to 1000 is 0.116334
Mean proportion of trailing zeroes in factorials to 10000 is 0.081267
The mean proportion dips permanently below 0.07 at 31549. (0.1s)
</pre>
=={{header|Python}}==
<langsyntaxhighlight lang="python">def facpropzeros(N, verbose = True):
proportions = [0.0] * N
fac, psum = 1, 0.0
Line 213 ⟶ 1,099:
 
print("The mean proportion dips permanently below 0.16 at {}.".format(n + 2))
</langsyntaxhighlight>{{out}}
<pre>
The mean proportion of 0 in factorials from 1 to 100 is 0.24675318616743216.
Line 221 ⟶ 1,107:
</pre>
The means can be plotted, showing a jump from 0 to over 0.25, followed by a slowly dropping curve:
<langsyntaxhighlight lang="python">import matplotlib.pyplot as plt
plt.plot([i+1 for i in range(len(props))], props)
</syntaxhighlight>
</lang>
=== Base 1000 version ===
{{trans|Go via Phix via Pascal}}
<syntaxhighlight lang="python">def zinit():
zc = [0] * 999
for x in range(1, 10):
zc[x - 1] = 2 # 00x
zc[10 * x - 1] = 2 # 0x0
zc[100 * x - 1] = 2 # x00
for y in range(10, 100, 10):
zc[y + x - 1] = 1 # 0yx
zc[10 * y + x - 1] = 1 # y0x
zc[10 * (y + x) - 1] = 1 # yx0
 
return zc
 
def meanfactorialdigits():
zc = zinit()
rfs = [1]
total, trail, first = 0.0, 1, 0
for f in range(2, 50000):
carry, d999, zeroes = 0, 0, (trail - 1) * 3
j, l = trail, len(rfs)
while j <= l or carry != 0:
if j <= l:
carry = rfs[j-1] * f + carry
 
d999 = carry % 1000
if j <= l:
rfs[j-1] = d999
else:
rfs.append(d999)
 
zeroes += 3 if d999 == 0 else zc[d999-1]
carry //= 1000
j += 1
 
while rfs[trail-1] == 0:
trail += 1
 
# d999 is a quick correction for length and zeros
d999 = rfs[-1]
d999 = 0 if d999 >= 100 else 2 if d999 < 10 else 1
 
zeroes -= d999
digits = len(rfs) * 3 - d999
total += zeroes / digits
ratio = total / f
if f in [100, 1000, 10000]:
print("The mean proportion of zero digits in factorials to {} is {}".format(f, ratio))
if ratio >= 0.16:
first = 0
elif first == 0:
first = f
 
print("The mean proportion dips permanently below 0.16 at {}.".format(first))
 
 
 
import time
TIME0 = time.perf_counter()
meanfactorialdigits()
print("\nTotal time:", time.perf_counter() - TIME0, "seconds.")
</syntaxhighlight>{{out}}
<pre>
The mean proportion of zero digits in factorials to 100 is 0.24675318616743216
The mean proportion of zero digits in factorials to 1000 is 0.20354455110316458
The mean proportion of zero digits in factorials to 10000 is 0.17300384824186707
The mean proportion dips permanently below 0.16 at 47332.
 
Total time: 648.3583232999999 seconds.
</pre>
=={{header|Raku}}==
Works, but depressingly slow for 10000.
 
<syntaxhighlight lang="raku" perl6line>sub postfix:<!> (Int $n) { ( constant factorial = 1, 1, |[\*] 2..* )[$n] }
sink 10000!; # prime the iterator to allow multithreading
 
sub zs ($n) { ( constant zero-share = (^Inf).race(:32batch).map: { (.!.comb.Bag){'0'} / .!.chars } )[$n+1] }
 
.say for (
Line 237 ⟶ 1,194:
,1000
,10000
).map: -> \n { "{n}: {([+] (^n).map: *.&zs) / n}" }</langsyntaxhighlight>
{{out}}
<pre>100: 0.2448544519902169624675318616743216
1000: 0.2033607504801116220354455110316458
10000: 0.1729875751067016217300384824186605
</pre>
 
=={{header|REXX}}==
<langsyntaxhighlight lang="rexx">/*REXX program computes the mean of the proportion of "0" digits a series of factorials.*/
parse arg $ /*obtain optional arguments from the CL*/
if $='' | $="," then $= 100 1000 10000 /*not specified? Then use the default.*/
Line 254 ⟶ 1,210:
!= ! * i /*calculate the factorial of BIG. */
end /*i*/
if pos('E', !)>0 then do /*if its inIn exponential format,? Then get EXP.*/
parse var ! 'E' x /*parse the exponent from the number. */
numeric digits x+1 /*set the decimal digits to X plus 1.*/
Line 275 ⟶ 1,231:
do k=1 for z; != ! * k; y= y + countstr(0, !) / length(!)
end /*k*/
return y/z</langsyntaxhighlight>
{{out|output|text=&nbsp; when using the default inputs:}}
<pre>
Line 284 ⟶ 1,240:
10,000 │ 0.1730038482418660531800366428930706156810278809057883361518852958446868172...
───────────┴────────────────────────────────────────────────────────────────────────────────
</pre>
=={{header|Rust}}==
{{trans|Phix}}
<syntaxhighlight lang="rust">fn init_zc() -> Vec<usize> {
let mut zc = vec![0; 1000];
zc[0] = 3;
for x in 1..=9 {
zc[x] = 2;
zc[10 * x] = 2;
zc[100 * x] = 2;
let mut y = 10;
while y <= 90 {
zc[y + x] = 1;
zc[10 * y + x] = 1;
zc[10 * (y + x)] = 1;
y += 10;
}
}
zc
}
 
fn main() {
use std::time::Instant;
let zc = init_zc();
let t0 = Instant::now();
let mut trail = 1;
let mut first = 0;
let mut total: f64 = 0.0;
let mut rfs = vec![1];
 
for f in 2..=50000 {
let mut carry = 0;
let mut d999: usize;
let mut zeroes = (trail - 1) * 3;
let len = rfs.len();
let mut j = trail - 1;
while j < len || carry != 0 {
if j < len {
carry += rfs[j] * f;
}
d999 = carry % 1000;
if j < len {
rfs[j] = d999;
} else {
rfs.push(d999);
}
zeroes += zc[d999];
carry /= 1000;
j += 1;
}
while rfs[trail - 1] == 0 {
trail += 1;
}
d999 = rfs[rfs.len() - 1];
d999 = if d999 < 100 {
if d999 < 10 {
2
} else {
1
}
} else {
0
};
zeroes -= d999;
let digits = rfs.len() * 3 - d999;
total += (zeroes as f64) / (digits as f64);
let ratio = total / (f as f64);
if ratio >= 0.16 {
first = 0;
} else if first == 0 {
first = f;
}
if f == 100 || f == 1000 || f == 10000 {
let duration = t0.elapsed();
println!(
"Mean proportion of zero digits in factorials to {} is {:.10}. ({}ms)",
f,
ratio,
duration.as_millis()
);
}
}
let duration = t0.elapsed();
println!(
"The mean proportion dips permanently below 0.16 at {}. ({}ms)",
first,
duration.as_millis()
);
}</syntaxhighlight>
 
{{out}}
<pre>
Mean proportion of zero digits in factorials to 100 is 0.2467531862. (0ms)
Mean proportion of zero digits in factorials to 1000 is 0.2035445511. (1ms)
Mean proportion of zero digits in factorials to 10000 is 0.1730038482. (149ms)
The mean proportion dips permanently below 0.16 at 47332. (4485ms)
</pre>
=={{header|Ruby}}==
<syntaxhighlight lang="ruby">[100, 1000, 10_000].each do |n|
v = 1
total_proportion = (1..n).sum do |k|
v *= k
digits = v.digits
Rational(digits.count(0), digits.size)
end
puts "The mean proportion of 0 in factorials from 1 to #{n} is #{(total_proportion/n).to_f}."
end</syntaxhighlight>
{{out}}
<pre>The mean proportion of 0 in factorials from 1 to 100 is 0.24675318616743222.
The mean proportion of 0 in factorials from 1 to 1000 is 0.20354455110316463.
The mean proportion of 0 in factorials from 1 to 10000 is 0.17300384824186604.
</pre>
=={{header|Sidef}}==
<syntaxhighlight lang="ruby">func mean_factorial_digits(n, d = 0) {
 
var v = 1
var total = 0.float
 
for k in (1..n) {
v *= k
total += v.digits.count(d)/v.len
}
 
total / n
}
 
say mean_factorial_digits(100)
say mean_factorial_digits(1000)
say mean_factorial_digits(10000)</syntaxhighlight>
{{out}}
<pre>
0.246753186167432217778415887197352699112940703327
0.203544551103164635640043803171145530298574116789
0.173003848241866053180036642893070615681027880906
</pre>
 
=={{header|Wren}}==
===Brute force===
{{libheader|Wren-big}}
{{libheader|Wren-fmt}}
Very slow indeed, 10.75 minutes to reach N = 10,000.
<langsyntaxhighlight ecmascriptlang="wren">import "./big" for BigInt
import "./fmt" for Fmt
 
var fact = BigInt.one
Line 305 ⟶ 1,396:
Fmt.print("$,6d = $12.10f", n, sum / n)
}
}</langsyntaxhighlight>
 
{{out}}
Line 313 ⟶ 1,404:
1,000 = 0.2035445511
10,000 = 0.1730038482
</pre>
<br>
==='String math' and base 1000===
{{trans|Phix}}
Around 60 times faster than before with 10,000 now being reached in about 10.5 seconds. Even the stretch goal is now viable and comes in at 5 minutes 41 seconds.
<syntaxhighlight lang="wren">import "./fmt" for Fmt
 
var rfs = [1] // reverse factorial(1) in base 1000
 
var init = Fn.new { |zc|
for (x in 1..9) {
zc[x-1] = 2 // 00x
zc[10*x - 1] = 2 // 0x0
zc[100*x - 1] = 2 // x00
var y = 10
while (y <= 90) {
zc[y + x - 1] = 1 // 0yx
zc[10*y + x - 1] = 1 // y0x
zc[10*(y + x) - 1] = 1 // yx0
y = y + 10
}
}
}
 
var zc = List.filled(999, 0)
init.call(zc)
var total = 0
var trail = 1
var first = 0
var firstRatio = 0
System.print("The mean proportion of zero digits in factorials up to the following are:")
for (f in 2..50000) {
var carry = 0
var d999 = 0
var zeros = (trail-1) * 3
var j = trail
var l = rfs.count
while (j <= l || carry != 0) {
if (j <= l) carry = rfs[j-1]*f + carry
d999 = carry % 1000
if (j <= l) {
rfs[j-1] = d999
} else {
rfs.add(d999)
}
zeros = zeros + ((d999 == 0) ? 3 : zc[d999-1])
carry = (carry/1000).floor
j = j + 1
}
while (rfs[trail-1] == 0) trail = trail + 1
// d999 = quick correction for length and zeros
d999 = rfs[-1]
d999 = (d999 < 100) ? ((d999 < 10) ? 2 : 1) : 0
zeros = zeros - d999
var digits = rfs.count * 3 - d999
total = total + zeros/digits
var ratio = total / f
if (ratio >= 0.16) {
first = 0
firstRatio = 0
} else if (first == 0) {
first = f
firstRatio = ratio
}
if (f == 100 || f == 1000 || f == 10000) {
Fmt.print("$,6d = $12.10f", f, ratio)
}
}
Fmt.write("$,6d = $12.10f", first, firstRatio)
System.print(" (stays below 0.16 after this)")
Fmt.print("$,6d = $12.10f", 50000, total/50000)</syntaxhighlight>
 
{{out}}
<pre>
The mean proportion of zero digits in factorials up to the following are:
100 = 0.2467531862
1,000 = 0.2035445511
10,000 = 0.1730038482
47,332 = 0.1599999958 (stays below 0.16 after this)
50,000 = 0.1596200546
</pre>
337

edits