/* GeoGebra - Dynamic Mathematics for Everyone http://www.geogebra.org This file is part of GeoGebra. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation. */ package org.geogebra.common.kernel.statistics; import org.geogebra.common.kernel.Construction; import org.geogebra.common.kernel.Kernel; import org.geogebra.common.kernel.SetRandomValue; import org.geogebra.common.kernel.algos.AlgoTwoNumFunction; import org.geogebra.common.kernel.commands.Commands; import org.geogebra.common.kernel.geos.GeoNumberValue; /** * Computes RandomNormal[a, b] * * @author Michael Borcherds */ public class AlgoRandomBinomial extends AlgoTwoNumFunction implements SetRandomValue { public AlgoRandomBinomial(Construction cons, String label, GeoNumberValue a, GeoNumberValue b) { super(cons, label, a, b); // output is random number cons.addRandomGeo(num); } @Override public Commands getClassName() { return Commands.RandomBinomial; } @Override public final void compute() { // int frac[] = {0,0}; // int [] frac = DecimalToFraction(b.getDouble(),0.00000001); // Application.debug(frac[0]+" "+frac[1]); if (input[0].isDefined() && input[1].isDefined()) { if (b.getDouble() < 0) { num.setUndefined(); } else { // disabled randomBinomialTRS() as it doesn't work well // eg when p is near 0.5 // http://www.geogebra.org/forum/viewtopic.php?f=8&t=18685 // num.setValue(randomBinomialTRS((int)a.getDouble(), // b.getDouble())); num.setValue( randomBinomial((int) a.getDouble(), b.getDouble())); } } else { num.setUndefined(); } } @Override public void setRandomValue(double d0) { double d = Math.round(Kernel.checkInteger(d0)); if (d >= 0 && d <= a.getDouble()) { num.setValue(d); num.updateRepaint(); } } private int randomBinomial(double n, double p) { int count = 0; for (int i = 0; i < n; i++) { if (kernel.getApplication().getRandomNumber() < p) { count++; } } return count; } // private static double halflog2pi = 0.5 * Math.log(2 * Math.PI); // private static double logtable[] = new double[10]; // private int[] DecimalToFraction(double Decimal, double AccuracyFactor) { // double FractionNumerator, FractionDenominator; // double DecimalSign; // double Z; // double PreviousDenominator; // double ScratchValue; // // int ret[] = {0,0}; // if (Decimal < 0.0) DecimalSign = -1.0; else DecimalSign = 1.0; // Decimal = Math.abs(Decimal); // if (Decimal == Math.floor(Decimal)) { // handles exact integers including // 0 // FractionNumerator = Decimal * DecimalSign; // FractionDenominator = 1.0; // ret[0] = (int)FractionNumerator; // ret[1] = (int)FractionDenominator; // return ret; // } // if (Decimal < 1.0E-19) { // X = 0 already taken care of // FractionNumerator = DecimalSign; // FractionDenominator = 9999999999999999999.0; // ret[0] = (int)FractionNumerator; // ret[1] = (int)FractionDenominator; // return ret; // } // if (Decimal > 1.0E19) { // FractionNumerator = 9999999999999999999.0*DecimalSign; // FractionDenominator = 1.0; // ret[0] = (int)FractionNumerator; // ret[1] = (int)FractionDenominator; // return ret; // } // Z = Decimal; // PreviousDenominator = 0.0; // FractionDenominator = 1.0; // do { // Z = 1.0/(Z - Math.floor(Z)); // ScratchValue = FractionDenominator; // FractionDenominator = FractionDenominator * Math.floor(Z) + // PreviousDenominator; // PreviousDenominator = ScratchValue; // FractionNumerator = Math.floor(Decimal * FractionDenominator + 0.5); // // Rounding Function // } while ( Math.abs((Decimal - (FractionNumerator /FractionDenominator))) // > AccuracyFactor && Z != Math.floor(Z)); // FractionNumerator = DecimalSign*FractionNumerator; // // ret[0] = (int)FractionNumerator; // ret[1] = (int)FractionDenominator; // return ret; // } }