package org.geogebra.common.kernel.advanced; import java.math.BigInteger; import org.geogebra.common.kernel.Construction; import org.geogebra.common.kernel.Kernel; import org.geogebra.common.kernel.algos.AlgoElement; import org.geogebra.common.kernel.commands.Commands; import org.geogebra.common.kernel.geos.GeoElement; import org.geogebra.common.kernel.geos.GeoNumberValue; import org.geogebra.common.kernel.geos.GeoText; import org.geogebra.common.util.StringUtil; /** * Allows conversion of numbers to different bases via ToBase[number, base] * * @author zbynek * */ public class AlgoToBase extends AlgoElement { private GeoNumberValue base; private GeoNumberValue number; private GeoText result; /** * @param c * construction * @param label * label for output * @param base * base * @param number * number */ public AlgoToBase(Construction c, String label, GeoNumberValue number, GeoNumberValue base) { super(c); this.base = base; this.number = number; result = new GeoText(cons); setInputOutput(); compute(); result.setLabel(label); } @Override protected void setInputOutput() { input = new GeoElement[] { number.toGeoElement(), base.toGeoElement() }; setOnlyOutput(result); setDependencies(); } /** * @return result as text */ public GeoText getResult() { return result; } @Override public void compute() { if (!number.isDefined() || !base.isDefined()) { result.setUndefined(); return; } int b = (int) base.getDouble(); if (b < 2 || b > 36) { result.setUndefined(); return; } int digits = kernel.format(1.0 / 9.0, result.getStringTemplate()) .length() - 2; double power = Math.round(Math.pow(b, digits)); double in = number.getDouble(); in = in + 1 / power > Math.ceil(in) ? Math.ceil(in) : in; BigInteger bi = BigInteger.valueOf((long) in); String intPart = StringUtil.toUpperCase(bi.toString(b)); if (Kernel.isInteger(in)) { result.setTextString(intPart); } else { double decimal = Math.round(power * (number.getDouble() - Math.floor(number.getDouble()))); bi = BigInteger.valueOf((long) decimal); String decimalPart = StringUtil.toUpperCase(bi.toString(b)); StringBuilder sb = new StringBuilder(digits); sb.append(intPart); sb.append('.'); for (int i = 0; i < digits - decimalPart.length(); i++) { sb.append('0'); } sb.append(decimalPart); result.setTextString(sb.toString()); } } @Override public Commands getClassName() { return Commands.ToBase; } }