Gerne, macht ja Spaß!
Ich will dich nicht verrückt machen! Aber ich hätte noch zwei gute Nachrichten und eine schlechte. 
Erst mal eine gute:
Die ganzen Anpassungen finde ich super und (fast) alles funktioniert! 
Jetzt die schlechte (aber keine Angst):
Der Rechner hat bei kleiner Solo-Hashrate H_{solo} genau das Problem mit dem Genauigkeitsverlust, das ich weiter oben angesprochen hatte. Unterhalb von ca. 40 kH/s geht gar nichts mehr. Darüber wird es erst etwas ungenau und bei größerem H_{solo} dann immer besser.
In beiden verwendeten Formeln ist die Ursache die gleiche. Nämlich dass die Summe einer großen und einer kleinen Double Zahl verarbeitet werden sollen.
P = 1 - (\frac{H_{rest}}{H_{rest} + H_{solo}})^{N} \tag{1}
P = 1 - \text{e}^{-\frac{H_{solo}}{H_{rest}}\frac{1-b^{-N}}{1-b^{-1}}} \tag{2}
In Formel (1) erhält man bei kleinem H_{solo} für den Bruch eine Zahl, die fast exakt 1 ist und erst weit hinter dem Komma wieder Stellen ungleich 9 hat (z.B. 0.99999999999245).
Da das Double Format nur ca. 16 Stellen Genauigkeit zulässt, wird alles dahinter unterschlagen. Ist H_{solo} also um mehr als 16 Größenordnungen kleiner als H_{rest}, wird der Bruch einfach 1 und P = 0.
In Formel (2) erhält man bei kleinem H_{solo} und kleinem N für den Exponenten eine Zahl, die fast exakt 0 ist und erst weit hinter dem Komma wieder Stellen ungleich 0 hat (z.B. -0.0000000000245).
Das Potenzieren mit Basis \text{e} entspricht bei kleinen Zahlen x näherungsweise \text{e}^{x} \approx 1 + x. Wieder erhält man also die Summe einer großen Zahl 1 und einer sehr kleinen Zahl x. Ist der Exponent x kleiner als 10^{-16}, wird im Double Format \text{e}^{x} \approx 1 + x = 1, also P = 0.
Man muss es also vermeiden Zahlen zu addieren, deren Größenordnung sich um mehr als die Double-Genauigkeit unterscheidet.
Jetzt die abschließende gute Nachricht:
Die Klasse Math biete extra hierfür die Methode Math.expm1() an, welche nicht \text{e}^{x} \approx 1 + x berechnet, sondern direkt \text{e}^{x} -1 \approx x. Da wir am Ende für P sowieso immer die Differenz zu 1 berechnen müssen, passt dass hervorragend.
Meine Problembeschreibung findet sich übrigens so ähnlich auch unter „Description“ in der Doku der beiden Methoden:
→ Math.exp() - JavaScript | MDN
→ Math.expm1() - JavaScript | MDN
Wir müssen also doch die beiden ursprünglichen Formeln heranziehen…
P = 1 - \text{e}^{-\frac{H_{solo}}{H_{rest}}N} \,\,\,\,\,\,\, für \,\,\,b = 1 \tag{3}
P = 1 - \text{e}^{-\frac{H_{solo}}{H_{rest}}\frac{1-b^{-N}}{1-b^{-1}}} \,\,\,\,\,\,\, für \,\,\,b \neq 1 \tag{4}
… wobei wir aber statt 1 - Math.exp(x) direkt - Math.expm1(x) verwenden.
function calculateChance (local, N, b) {
if (b === 1) {
return (- Math.expm1(-(local/hashrate) * N)) * 100;
}
return (- Math.expm1(-(local/hashrate) * (1 - Math.pow(b, -N)) / (1 - Math.pow(b, -1)))) * 100;
}
Damit ist der Rechner bei sehr kleinen bis zu realistischen großen Werten genau.