Returns the base-10 logarithm of x, rounded according to the specified rounding mode. @throws IllegalArgumentException if x <= 0 @throws ArithmeticException if mode is RoundingMode#UNNECESSARY and x is not a power of ten
(BigInteger x, RoundingMode mode)
| 149 | */ |
| 150 | |
| 151 | @GwtIncompatible // TODO |
| 152 | @SuppressWarnings("fallthrough") |
| 153 | public static int log10(BigInteger x, RoundingMode mode) { |
| 154 | checkPositive("x", x); |
| 155 | if (fitsInLong(x)) { |
| 156 | return LongMath.log10(x.longValue(), mode); |
| 157 | } |
| 158 | int approxLog10 = (int) (log2(x, FLOOR) * LN_2 / LN_10); |
| 159 | BigInteger approxPow = BigInteger.TEN.pow(approxLog10); |
| 160 | int approxCmp = approxPow.compareTo(x); |
| 161 | |
| 162 | /* |
| 163 | * We adjust approxLog10 and approxPow until they're equal to floor(log10(x)) and |
| 164 | * 10^floor(log10(x)). |
| 165 | */ |
| 166 | if (approxCmp > 0) { |
| 167 | /* |
| 168 | * The code is written so that even completely incorrect approximations will still yield the |
| 169 | * correct answer eventually, but in practice this branch should almost never be entered, and |
| 170 | * even then the loop should not run more than once. |
| 171 | */ |
| 172 | do { |
| 173 | approxLog10--; |
| 174 | approxPow = approxPow.divide(BigInteger.TEN); |
| 175 | approxCmp = approxPow.compareTo(x); |
| 176 | } while (approxCmp > 0); |
| 177 | } else { |
| 178 | BigInteger nextPow = BigInteger.TEN.multiply(approxPow); |
| 179 | int nextCmp = nextPow.compareTo(x); |
| 180 | while (nextCmp <= 0) { |
| 181 | approxLog10++; |
| 182 | approxPow = nextPow; |
| 183 | approxCmp = nextCmp; |
| 184 | nextPow = BigInteger.TEN.multiply(approxPow); |
| 185 | nextCmp = nextPow.compareTo(x); |
| 186 | } |
| 187 | } |
| 188 | int floorLog = approxLog10; |
| 189 | BigInteger floorPow = approxPow; |
| 190 | int floorCmp = approxCmp; |
| 191 | switch (mode) { |
| 192 | case UNNECESSARY: |
| 193 | checkRoundingUnnecessary(floorCmp == 0); |
| 194 | // fall through |
| 195 | case FLOOR: |
| 196 | case DOWN: |
| 197 | return floorLog; |
| 198 | case CEILING: |
| 199 | case UP: |
| 200 | return floorPow.equals(x) ? floorLog : floorLog + 1; |
| 201 | case HALF_DOWN: |
| 202 | case HALF_UP: |
| 203 | case HALF_EVEN: |
| 204 | // Since sqrt(10) is irrational, log10(x) - floorLog can never be exactly 0.5 |
| 205 | BigInteger x2 = x.pow(2); |
| 206 | BigInteger halfPowerSquared = floorPow.pow(2).multiply(BigInteger.TEN); |
| 207 | return (x2.compareTo(halfPowerSquared) <= 0) ? floorLog : floorLog + 1; |
| 208 | default: |
nothing calls this directly
no test coverage detected