1 24 25 package com.mckoi.util; 26 27 import java.math.BigDecimal ; 28 import java.math.BigInteger ; 29 30 37 38 public final class BigNumber extends Number { 39 40 static final long serialVersionUID = -8681578742639638105L; 41 42 45 private final static byte NEG_INF_STATE = 1; 46 private final static byte POS_INF_STATE = 2; 47 private final static byte NaN_STATE = 3; 48 49 53 private byte number_state; 54 55 58 private BigDecimal big_decimal; 59 60 63 private long long_representation; 64 65 69 private byte byte_count = 120; 70 71 74 private BigNumber(byte number_state, BigDecimal big_decimal) { 75 this.number_state = number_state; 76 if (number_state == 0) { 77 setBigDecimal(big_decimal); 78 } 79 } 80 81 private BigNumber(byte[] buf, int scale, byte state) { 82 this.number_state = state; 83 if (number_state == 0) { 84 BigInteger bigint = new BigInteger (buf); 85 setBigDecimal(new BigDecimal (bigint, scale)); 86 } 87 } 88 89 private void setBigDecimal(BigDecimal big_decimal) { 91 this.big_decimal = big_decimal; 92 if (big_decimal.scale() == 0) { 93 BigInteger bint = big_decimal.toBigInteger(); 94 int bit_count = big_decimal.toBigInteger().bitLength(); 95 if (bit_count < 30) { 96 this.long_representation = bint.longValue(); 97 this.byte_count = 4; 98 } 99 else if (bit_count < 60) { 100 this.long_representation = bint.longValue(); 101 this.byte_count = 8;; 102 } 103 } 104 } 105 106 110 public boolean canBeRepresentedAsLong() { 111 return byte_count <= 8; 112 } 113 114 118 public boolean canBeRepresentedAsInt() { 119 return byte_count <= 4; 120 } 121 122 126 public int getScale() { 127 if (number_state == 0) { 128 return big_decimal.scale(); 129 } 130 else { 131 return -1; 132 } 133 } 134 135 140 public byte getState() { 141 return number_state; 142 } 143 144 147 private byte getInverseState() { 148 if (number_state == NEG_INF_STATE) { 149 return POS_INF_STATE; 150 } 151 else if (number_state == POS_INF_STATE) { 152 return NEG_INF_STATE; 153 } 154 else { 155 return number_state; 156 } 157 } 158 159 162 public byte[] toByteArray() { 163 if (number_state == 0) { 164 return big_decimal.movePointRight( 165 big_decimal.scale()).toBigInteger().toByteArray(); 166 } 170 else { 171 return new byte[0]; 172 } 173 } 174 175 178 public String toString() { 179 switch (number_state) { 180 case(0): 181 return big_decimal.toString(); 182 case(NEG_INF_STATE): 183 return "-Infinity"; 184 case(POS_INF_STATE): 185 return "Infinity"; 186 case(NaN_STATE): 187 return "NaN"; 188 default: 189 throw new Error ("Unknown number state"); 190 } 191 } 192 193 196 public double doubleValue() { 197 switch (number_state) { 198 case(0): 199 return big_decimal.doubleValue(); 200 case(NEG_INF_STATE): 201 return Double.NEGATIVE_INFINITY; 202 case(POS_INF_STATE): 203 return Double.POSITIVE_INFINITY; 204 case(NaN_STATE): 205 return Double.NaN; 206 default: 207 throw new Error ("Unknown number state"); 208 } 209 } 210 211 214 public float floatValue() { 215 switch (number_state) { 216 case(0): 217 return big_decimal.floatValue(); 218 case(NEG_INF_STATE): 219 return Float.NEGATIVE_INFINITY; 220 case(POS_INF_STATE): 221 return Float.POSITIVE_INFINITY; 222 case(NaN_STATE): 223 return Float.NaN; 224 default: 225 throw new Error ("Unknown number state"); 226 } 227 } 228 229 232 public long longValue() { 233 if (canBeRepresentedAsLong()) { 234 return long_representation; 235 } 236 switch (number_state) { 237 case(0): 238 return big_decimal.longValue(); 239 default: 240 return (long) doubleValue(); 241 } 242 } 243 244 247 public int intValue() { 248 if (canBeRepresentedAsLong()) { 249 return (int) long_representation; 250 } 251 switch (number_state) { 252 case(0): 253 return big_decimal.intValue(); 254 default: 255 return (int) doubleValue(); 256 } 257 } 258 259 262 public short shortValue() { 263 return (short) intValue(); 264 } 265 266 269 public byte byteValue() { 270 return (byte) intValue(); 271 } 272 273 274 278 public BigDecimal asBigDecimal() { 279 if (number_state == 0) { 280 return big_decimal; 281 } 282 else { 283 throw new ArithmeticException ( 284 "NaN, +Infinity or -Infinity can't be translated to a BigDecimal"); 285 } 286 } 287 288 293 public int compareTo(BigNumber number) { 294 295 if (this == number) { 296 return 0; 297 } 298 299 if (number_state == 0) { 301 302 if (canBeRepresentedAsLong() && number.canBeRepresentedAsLong()) { 304 if (long_representation > number.long_representation) { 306 return 1; 307 } 308 else if (long_representation < number.long_representation) { 309 return -1; 310 } 311 else { 312 return 0; 313 } 314 315 } 316 317 if (number.number_state == 0) { 320 return big_decimal.compareTo(number.big_decimal); 321 } 322 else { 323 if (number.number_state == POS_INF_STATE || 326 number.number_state == NaN_STATE) { 327 return -1; 328 } 329 else if (number.number_state == NEG_INF_STATE) { 331 return 1; 332 } 333 else { 334 throw new Error ("Unknown number state."); 335 } 336 } 337 } 338 else { 339 if (number.number_state == 0) { 342 if (number_state == NEG_INF_STATE) { 344 return -1; 345 } 346 else if (number_state == POS_INF_STATE || 348 number_state == NaN_STATE) { 349 return 1; 350 } 351 else { 352 throw new Error ("Unknown number state."); 353 } 354 } 355 else { 356 return (int) (number_state - number.number_state); 360 } 361 } 362 } 363 364 369 public boolean equals(Object ob) { 370 BigNumber bnum = (BigNumber) ob; 371 if (number_state != 0) { 372 return (number_state == bnum.number_state); 373 } 374 else { 375 return big_decimal.equals(bnum.big_decimal); 376 } 377 } 378 379 380 381 382 385 private final static BigDecimal BD_ZERO = new BigDecimal (0); 386 387 388 389 391 public BigNumber bitWiseOr(BigNumber number) { 392 if (number_state == 0 && getScale() == 0 && 393 number.number_state == 0 && number.getScale() == 0) { 394 BigInteger bi1 = big_decimal.toBigInteger(); 395 BigInteger bi2 = number.big_decimal.toBigInteger(); 396 return new BigNumber((byte) 0, new BigDecimal (bi1.or(bi2))); 397 } 398 else { 399 return null; 400 } 401 } 402 403 public BigNumber add(BigNumber number) { 404 if (number_state == 0) { 405 if (number.number_state == 0) { 406 return new BigNumber((byte) 0, big_decimal.add(number.big_decimal)); 407 } 408 else { 409 return new BigNumber(number.number_state, null); 410 } 411 } 412 else { 413 return new BigNumber(number_state, null); 414 } 415 } 416 417 public BigNumber subtract(BigNumber number) { 418 if (number_state == 0) { 419 if (number.number_state == 0) { 420 return new BigNumber((byte) 0, big_decimal.subtract(number.big_decimal)); 421 } 422 else { 423 return new BigNumber(number.getInverseState(), null); 424 } 425 } 426 else { 427 return new BigNumber(number_state, null); 428 } 429 } 430 431 public BigNumber multiply(BigNumber number) { 432 if (number_state == 0) { 433 if (number.number_state == 0) { 434 return new BigNumber((byte) 0, big_decimal.multiply(number.big_decimal)); 435 } 436 else { 437 return new BigNumber(number.number_state, null); 438 } 439 } 440 else { 441 return new BigNumber(number_state, null); 442 } 443 } 444 445 public BigNumber divide(BigNumber number) { 446 if (number_state == 0) { 447 if (number.number_state == 0) { 448 BigDecimal div_by = number.big_decimal; 449 if (div_by.compareTo(BD_ZERO) != 0) { 450 return new BigNumber((byte) 0, 451 big_decimal.divide(div_by, 10, BigDecimal.ROUND_HALF_UP)); 452 } 453 } 454 } 455 return new BigNumber((byte) 3, null); 457 } 458 459 public BigNumber abs() { 460 if (number_state == 0) { 461 return new BigNumber((byte) 0, big_decimal.abs()); 462 } 463 else if (number_state == NEG_INF_STATE) { 464 return new BigNumber(POS_INF_STATE, null); 465 } 466 else { 467 return new BigNumber(number_state, null); 468 } 469 } 470 471 public int signum() { 472 if (number_state == 0) { 473 return big_decimal.signum(); 474 } 475 else if (number_state == NEG_INF_STATE) { 476 return -1; 477 } 478 else { 479 return 1; 480 } 481 } 482 483 public BigNumber setScale(int d, int round_enum) { 484 if (number_state == 0) { 485 return new BigNumber((byte) 0, big_decimal.setScale(d, round_enum)); 486 } 487 return this; 489 } 490 491 public BigNumber sqrt() { 492 double d = doubleValue(); 493 d = Math.sqrt(d); 494 return fromDouble(d); 495 } 496 497 498 499 500 501 503 506 public static BigNumber fromDouble(double value) { 507 if (value == Double.NEGATIVE_INFINITY) { 508 return NEGATIVE_INFINITY; 509 } 510 else if (value == Double.POSITIVE_INFINITY) { 511 return POSITIVE_INFINITY; 512 } 513 else if (value != value) { 514 return NaN; 515 } 516 return new BigNumber((byte) 0, new BigDecimal (Double.toString(value))); 517 } 518 519 522 public static BigNumber fromFloat(float value) { 523 if (value == Float.NEGATIVE_INFINITY) { 524 return NEGATIVE_INFINITY; 525 } 526 else if (value == Float.POSITIVE_INFINITY) { 527 return POSITIVE_INFINITY; 528 } 529 else if (value != value) { 530 return NaN; 531 } 532 return new BigNumber((byte) 0, new BigDecimal (Float.toString(value))); 533 } 534 535 538 public static BigNumber fromLong(long value) { 539 return new BigNumber((byte) 0, BigDecimal.valueOf(value)); 540 } 541 542 545 public static BigNumber fromInt(int value) { 546 return new BigNumber((byte) 0, BigDecimal.valueOf(value)); 547 } 548 549 552 public static BigNumber fromString(String str) { 553 if (str.equals("Infinity")) { 554 return POSITIVE_INFINITY; 555 } 556 else if (str.equals("-Infinity")) { 557 return NEGATIVE_INFINITY; 558 } 559 else if (str.equals("NaN")) { 560 return NaN; 561 } 562 else { 563 return new BigNumber((byte) 0, new BigDecimal (str)); 564 } 565 } 566 567 570 public static BigNumber fromBigDecimal(BigDecimal val) { 571 return new BigNumber((byte) 0, val); 572 } 573 574 577 public static BigNumber fromData(byte[] buf, int scale, byte state) { 578 if (state == 0) { 579 if (scale == 0 && buf.length == 1) { 581 if (buf[0] == 0) { 582 return BIG_NUMBER_ZERO; 583 } 584 else if (buf[0] == 1) { 585 return BIG_NUMBER_ONE; 586 } 587 } 588 return new BigNumber(buf, scale, state); 589 } 590 else if (state == NEG_INF_STATE) { 591 return NEGATIVE_INFINITY; 592 } 593 else if (state == POS_INF_STATE) { 594 return POSITIVE_INFINITY; 595 } 596 else if (state == NaN_STATE) { 597 return NaN; 598 } 599 else { 600 throw new Error ("Unknown number state."); 601 } 602 } 603 604 605 608 public static final BigNumber NEGATIVE_INFINITY = 609 new BigNumber(NEG_INF_STATE, null); 610 public static final BigNumber POSITIVE_INFINITY = 611 new BigNumber(POS_INF_STATE, null); 612 public static final BigNumber NaN = new BigNumber(NaN_STATE, null); 613 614 617 public static final BigNumber BIG_NUMBER_ZERO = BigNumber.fromLong(0); 618 public static final BigNumber BIG_NUMBER_ONE = BigNumber.fromLong(1); 619 620 } 621 | Popular Tags |