目录
前言
Dart中只有BigInt没有BigDecimal,所以需要手动去实现BigDecimal。
如果我的代码帮到你,请给我点个赞。
API
构造函数
- BigDecimal([dynamic number]) 将任意toString后能表示为小数的类型转换为BigDecimal
- BigDecimal.fromReal(List real) 将BigDecimal实数部分转换为BigDecimal
- BigDecimal.fromDecimal(List decimal) 将BigDecimal小数部分转换为BigDecimal
四则及幂运算
- BigDecimal operator + (dynamic number)
- BigDecimal operator - (dynamic number)
- BigDecimal operator * (dynamic number)
- BigDecimal operator / (dynamic number)
- BigDecimal pow(int n) 快速幂运算
其他
- BigDecimal disablePrecisionLimit() 取消除法运算精度,可能导致程序无限循环进行除法运算
- BigDecimal setDivMaxPrecision(int precision) 设置除法运算最大的精度,默认1000
- BigDecimal clone() 克隆BigDecimal对象
- BigDecimal abs() 取正
- List real() 获取实数部分
- List decimal() 获取小数部分
代码
BigDecimal.dart
dart
import 'dart:math' as Math;
//TODO StringBuilder自己想办法解决
import 'package:module_utils/tools/StringBuilder.dart';
///高精度大数
///
/// eg: [123][1][2][3].[123][1][123] => 123 000000001 000000002 000000003.000000123 000000001 000000123
class BigDecimal{
static get nan => BigDecimal("nan");
static get zero => BigDecimal("0.0");
static get one => BigDecimal("1.0");
static get two => BigDecimal("2.0");
//实数部分 非空 [高位,低位] 值∈[0, 1E9-1]
final List<int> _real = [];
//小数部分 非空 [高位,低位] 值∈[0, 1E9-1]
final List<int> _decimal = [];
//正负号 true:+ false:-
bool _sign = true;
//无穷大 除数为0时,商为无穷大
bool _nan = false;
//sqrt(int.max = 9223372036854775807) = 3037000499
//每个list元素最大的值 1E10 - 1
static const int _MaxUnit = 999999999;
static const int _1E9 = 1000000000;
static BigDecimal min(BigDecimal b1, BigDecimal b2){
return b1<b2 ? b1 : b2;
}
static BigDecimal max(BigDecimal b1, BigDecimal b2){
return b1<b2 ? b2 : b1;
}
static int _lengthOfNormal([int num]) => 9;
//求实数最高元素的位数长度 eg: 123456 => 6
static int _lengthOfReal(int num){
return _splitReal(num).length;
}
//求小数最低元素的位数长度 eg: 1234560 = 00123456 => 8
static int _lengthOfDecimal(int num){
return _splitDecimal(num).length;
}
//将整数拆分 eg: 123456 => [0,0,0,1,2,3,4,5,6]
static List<int> _splitNormal(int num){
return List.filled(9, 1).asMap().keys.map((e) => num~/Math.pow(10,e)%10).toList().reversed.toList();
}
//将实数高位元素拆分 eg: 123456 => [1,2,3,4,5,6]
static List<int> _splitReal(int num){
return List.filled(9, 1).asMap().keys.map((e) => num~/Math.pow(10,e)%10).toList().reversed.skipWhile((value) => value==0).toList();
}
//将小数低位元素拆分 eg: 123456000 => [1,2,3,4,5,6] err:0000100000
static List<int> _splitDecimal(int num){
return num == 0 ? [0] :List.filled(9, 1).asMap().keys.map((e) => num~/Math.pow(10,e)%10).toList().skipWhile((value) => value==0).toList().reversed.toList();
}
//将整数数组拆分 eg: [123,456,789] => [0,0,0,0,0,0,1,2,3,0,0,0,0,0,0,4,5,6,0,0,0,0,0,0,7,8,9]
static List<int> __splitNormal(List<int> numbers){
return numbers.map((e) => _splitNormal(e)).expand((e) => e).toList();
}
//将实数元素数组拆分 eg: [123,456,7890] => [1,2,3,0,0,0,0,0,0,4,5,6,0,0,0,0,0,7,8,9,0]
static List<int> __splitReal(List<int> numbers){
return __splitNormal(numbers).skipWhile((value) => value==0).toList();
}
//将小数元素数组拆分 eg: [123,456,7890] => [0,0,0,0,0,0,1,2,3,0,0,0,0,0,0,4,5,6,0,0,0,0,0,7,8,9]
static List<int> __splitDecimal(List<int> numbers){
var result = __splitNormal(numbers);
for(int i=result.length-1; i>0; --i){
if(result[i] == 0) result.removeLast();
else break;
}
return result;
}
//将按位分割的整数数组组合成一个整数 eg: [1,2,3,4,5,6] => 123456
static int _combineNormal(List<int> numbers){
return int.parse(numbers.join());
}
//将按位分割的整数数组组合成一个实数高位元素 eg: [0,1,2,3,4,5,6] => 123456
static int _combineReal(List<int> numbers){
return int.parse(numbers.skipWhile((e) => e==0).join().padLeft(1,"0"));
}
//将按位分割的整数数组组合成一个小数低位元素 eg: [1,2,3,4,5,6] => 123456000
static int _combineDecimal(List<int> numbers){
return numbers.length==1&&numbers[0]==0 ? 0 : int.parse(numbers.join().padRight(9,"0"));
}
//将按位分割的整数数组组组合成大数实数元素数组 eg: [1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7] => [12345678,901234567]
static List<int> __combineReal(List<int> numbers){
List<int> nums = numbers.skipWhile((e) => e==0).toList();
return List.filled(nums.length~/10 + (nums.length%10==0?0:1), 0)
.asMap()
.keys
.map((e) => _combineReal(nums.sublist(Math.max(0,nums.length-(10*(e+1))), nums.length-(10*e))))
.toList();
}
//将按位分割的整数数组组组合成大数小数元素数组 eg: [1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7] => [123456789,12345670]
static List<int> __combineDecimal(List<int> numbers){
var nums = []..addAll(numbers);
while(nums.length%10 != 0) nums.add(0);
return List.filled(nums.length~/10 + (nums.length%10==0?0:1), 0)
.asMap()
.keys
.map(
(e) =>
e==(nums.length~/10-1)
? _combineDecimal(nums.sublist(10*e, Math.min(10*(e+1), nums.length)))
: _combineReal (nums.sublist(10*e, 10*(e+1)))
)
.toList();
}
static List<int> _parseReal(String part){
List<int> result = [];
while(part.length>0){
int length = part.length;
int index = Math.max(length-9, 0);
int num = int.parse(part.substring(index, part.length));
part = part.substring(0, index);
result.insert(0,num);
}
if(result.isEmpty) result.add(0);
return result;
}
static List<int> _parseDecimal(String part){
List<int> result = [];
while(part.length>0){
int length = part.length;
int index = Math.min(length, 9);
int num = int.parse(part.substring(0,index).padRight(9,"0"));
part = part.substring(index);
result.add(num);
}
if(result.isEmpty) result.add(0);
return result;
}
BigDecimal.fromReal(List<int> real){
_real .addAll(real);
_decimal.add(0);
}
BigDecimal.fromDecimal(List<int> decimal){
_real .add(0);
_decimal.addAll(decimal);
}
BigDecimal([dynamic number]){
try{
if(number == null) return;
if(number is BigDecimal){
_real.addAll(number._real);
_decimal.addAll(number._decimal);
_sign = number._sign;
_nan = number._nan;
return;
}
if(number is double){
if(number.isNaN){
_nan = true;
return;
}
BigDecimal decimal = BigDecimal(number.toString());
_real.addAll(decimal._real);
_decimal.addAll(decimal._decimal);
_sign = decimal._sign;
_nan = decimal._nan;
return;
}
if(number is int) {
_sign = number>-1;
_real.add(number.abs());
_nan = number.isNaN;
return;
}
String strNumber = number.toString().trim();
if(strNumber.toLowerCase() == "nan"){
_sign = true;
_nan = true;
return;
}
_nan = false;
String num = "";
//判断正负号
for(int i=0,ni=strNumber.length; i<ni; ++i){
if(strNumber.codeUnitAt(i)=='-'.codeUnitAt(0)){
_sign = false;
break;
}
if(strNumber.codeUnitAt(i)=='.'.codeUnitAt(0)){
_sign = true;
break;
}
if(strNumber.codeUnitAt(i)>='0'.codeUnitAt(0) && strNumber.codeUnitAt(i)<='9'.codeUnitAt(0)){
_sign = true;
break;
}
}
//格式化
for(int i=0,ni=strNumber.length; i<ni; ++i){
if(strNumber.codeUnitAt(i)>='0'.codeUnitAt(0) && strNumber.codeUnitAt(i)<='9'.codeUnitAt(0)){
num += strNumber.substring(i,i+1);
}
if(strNumber.codeUnitAt(i)=='.'.codeUnitAt(0) && num.indexOf(".")<0){
num += strNumber.substring(i,i+1);
}
}
if(num.length == 0) num = "0.0";
else if(num.indexOf(".")<0) num = num+".0";
int index = num.indexOf(".");
String strR = num.substring(0, index);
String strD = num.substring(index+1);
_real .addAll(_parseReal (strR));
_decimal.addAll(_parseDecimal(strD));
}
finally{
if(_real .isEmpty) _real .add(0);
if(_decimal.isEmpty) _decimal.add(0);
}
}
int compare(BigDecimal another){
if(_nan && !another._nan) return 1;
if(!_nan && another._nan) return -1;
if(_sign && !another._sign) return 1;
if(!_sign && another._sign) return -1;
bool sign = _sign;
//判断实数部分
if(_real.length > another._real.length) return sign ? 1 : -1;
if(_real.length < another._real.length) return sign ? -1 : 1;
for(int i=0,ni=_real.length; i<ni; ++i){
if(_real[i]>another._real[i]) return sign ? 1 : -1;
if(_real[i]<another._real[i]) return sign ? -1 : 1;
}
//以下实数部分相等
//判断小数部分
//判断高位
for(int i=0, ni=Math.min(_decimal.length, another._decimal.length)-1; i<ni;++i){
if(_decimal[i]>another._decimal[i]) return sign ? 1 : -1;
if(_decimal[i]<another._decimal[i]) return sign ? -1 : 1;
}
//将整数各个位分割以便判断低位
int index = Math.min(_decimal.length, another._decimal.length)-1;
List<int> num1 = List.filled(10, 1).asMap().keys.map((e) => _decimal[index]~/Math.pow(10,e)%10).toList().reversed.toList();
List<int> num2 = List.filled(10, 1).asMap().keys.map((e) => another._decimal[index]~/Math.pow(10,e)%10).toList().reversed.toList();
for(int i=0,ni=Math.min(num1.length, num2.length); i<ni;++i){
if(num1[i]>num2[i]) return sign ? 1 : -1;
if(num1[i]<num2[i]) return sign ? -1 : 1;
}
if(num1.length>num2.length) return sign ? 1 : -1;
if(num2.length<num2.length) return sign ? -1 : 1;
if(_decimal.length > another._decimal.length) return sign ? 1 : -1;
if(_decimal.length < another._decimal.length) return sign ? -1 : 1;
return 0;
}
bool operator < (dynamic number) => this.compare(BigDecimal(number)) == -1;
bool operator > (dynamic number) => this.compare(BigDecimal(number)) == 1;
bool operator == (dynamic number) => this.compare(BigDecimal(number)) == 0;
BigDecimal operator + (dynamic number){
BigDecimal another = BigDecimal(number);
if(_nan | another._nan) return nan;
//符号不一致
if(_sign ^ another._sign){
//当做减法处理
if(_sign) return this - another.abs();
return another - abs();
}
//符号一致处理
//region 小数部分
List<int> dec1 = _decimal;
List<int> dec2 = another._decimal;
int decLen1 = dec1.length;
int decLen2 = dec2.length;
// 计算小数公共元素的长度
int decCommonLen = Math.min(decLen1, decLen2);
// 小数计算结果存放
List<int> decSum = []..addAll(dec1.sublist(decCommonLen))
..addAll(dec2.sublist(decCommonLen));
// 进位标记
bool carry = false;
// 小数公共元素数组求和
for(int i=decCommonLen-1; i>-1; --i){
int sum = dec1[i] + dec2[i] + (carry?1:0);
carry = sum >= _1E9;
if(carry) sum = sum%_1E9;
decSum.insert(0, sum);
}
// 小数格式化
for(int i=decSum.length-1; i>0; --i){
if(decSum[i]==0) decSum.removeLast();
else break;
}
//endregion
//region 实数部分
List<int> real1 = _real;
List<int> real2 = another._real;
int realLen1 = real1.length;
int realLen2 = real2.length;
List<int> realSum = [];
// 公共部分求和
for(int i=realLen1-1, j=realLen2-1; j>-1||i>-1; --i,--j){
int sum =(i<0?0:real1[i]) + (j<0?0:real2[j]) + (carry?1:0);
carry = sum >= _1E9;
if(carry) sum = sum%_1E9;
realSum.insert(0, sum);
}
if(carry) realSum.insert(0, 1);
//endregion
return BigDecimal()
.._nan = false
.._sign = _sign
.._real.clear()
.._real.addAll(realSum)
.._decimal.clear()
.._decimal.addAll(decSum);
}
BigDecimal operator - (dynamic number){
BigDecimal another = BigDecimal(number);
if(_nan | another._nan) return nan;
//符号不一致
if(_sign ^ another._sign){
//当做加法处理
if(_sign) return this + another.abs();
return (abs() + another.abs()).._sign = false;
}
//符号一致且都是正数
if(_sign){
//减不过就换位减
if(this < another){
return (another - this).._sign = false;
}
}
//符号一致且都是负数
else{
//-a - -b => b - a
return another.abs() - abs();
}
bool borrow = false;
//region 小数部分
List<int> dec1 = _decimal;
List<int> dec2 = another._decimal;
int decLen1 = dec1.length;
int decLen2 = dec2.length;
List<int> decSub = [];
// 求差
for(int i=Math.max(decLen1,decLen2)-1; i>-1; --i){
int num1 = i < decLen1 ? dec1[i] : 0;
int num2 = i < decLen2 ? dec2[i] : 0;
int sub = num1 - num2 - (borrow?1:0);
borrow = sub<0;
if(borrow) sub += _1E9;
decSub.insert(0, sub);
}
// 小数格式化
for(int i=decSub.length-1; i>0; --i){
if(decSub[i]==0) decSub.removeLast();
else break;
}
//endregion
//region 实数部分
List<int> real1 = _real;
List<int> real2 = another._real;
int realLen1 = real1.length;
int realLen2 = real2.length;
List<int> realSub = [];
// 求差
for(int idx1=realLen1-1, idx2=realLen2-1, i=Math.max(realLen1, realLen2); i>0; --i,--idx1,--idx2){
int sub = (idx1<0?0:real1[idx1]) - (idx2<0?0:real2[idx2]) - (borrow?1:0);
borrow = sub<0;
if(borrow) sub += _1E9;
realSub.insert(0, sub);
}
// 实数格式化
for(int i=0, ni=realSub.length-1; i<ni; ++i){
if(realSub[0]==0) realSub.removeAt(0);
else break;
}
//endregion
return BigDecimal()
.._nan = false
.._sign = !borrow
.._real.clear()
.._real.addAll(realSub)
.._decimal.clear()
.._decimal.addAll(decSub);
}
BigDecimal operator * (dynamic number){
BigDecimal another = BigDecimal(number);
if(_nan | another._nan) return nan;
if(this == zero || another == zero) return zero;
if(this == one) return another;
if(another == one) return this.clone();
//将两个数拆分成位数组
List<int> dec1 = _decimal;
List<int> dec2 = another._decimal;
int decLen1 = dec1.length;
int decLen2 = dec2.length;
int decMulLen = decLen1 + decLen2;
List<int> real1 = _real;
List<int> real2 = another._real;
List<int> num1 = []..addAll(real1)..addAll(dec1);
List<int> num2 = []..addAll(real2)..addAll(dec2);
int numLen1 = num1.length;
int numLen2 = num2.length;
int numMulLen = numLen1 + numLen2;//可能的最大长度
//计算结果
List<int> numMul = List.filled(numMulLen+1, 0);
Function(int, int) add = (int index, int number){
numMul[index] += number;
int carry = numMul[index]~/_1E9;
while(carry>0){
numMul[index] %= _1E9;
numMul[--index] += carry;
carry = numMul[index]~/_1E9;
}
};
for(int i=numLen2-1, idx2=0, idx3=numMulLen; i>-1; --i,++idx2,idx3=numMulLen-idx2){
for(int j=numLen1-1, idx1=numMulLen-1-idx2; j>-1; --j,--idx1,--idx3){
int mul = num2[i]*num1[j];
add(idx3, mul);
}
}
List<int> real = numMul.sublist(0 , numMul.length - decMulLen);
List<int> decimal = numMul.sublist(numMul.length - decMulLen);
while(real.length>1){
if(real[0]==0) real.removeAt(0);
else break;
}
// 小数格式化
for(int i=decimal.length-1; i>0; --i){
if(decimal[i]==0) decimal.removeLast();
else break;
}
return BigDecimal()
.._sign = !(_sign ^ another._sign)
.._nan = false
.._real.clear()
.._real.addAll(real)
.._decimal.clear()
.._decimal.addAll(decimal);
}
BigDecimal operator / (dynamic number){
BigDecimal another = BigDecimal(number);
if(_nan | another._nan) return nan;
if(this == zero) return zero;
if(another == zero) return nan;
//将两个数拆分成元素数组
List<int> dec1 = _decimal;
List<int> dec2 = another._decimal;
List<int> real1 = _real;
List<int> real2 = another._real;
List<int> num1 = []..addAll(real1)..addAll(dec1);
List<int> num2 = []..addAll(real2)..addAll(dec2);
//初始化除数的倍数
final Map<int, BigDecimal> mTimes = {0:BigDecimal.zero, 1:BigDecimal.fromReal(num2)};
Function(BigDecimal, BigDecimal) add = (num1,num2) => BigDecimal.fromReal((num1+num2)._real);
Function(int) timesOfDivisor;
timesOfDivisor = (time){
BigDecimal value = mTimes[time];
if(value != null) return value;
value = add(timesOfDivisor(time~/2 + (time%2==0?0:1)), timesOfDivisor(time~/2));
mTimes[time] = value;
return value;
};
//region 二分减法
//b1~/b2 => [quotient, remainder]
Function(BigDecimal, BigDecimal) binSub = (BigDecimal b1, BigDecimal b2){
//平均计算 log2(10)≈3 log2(1E9)≈30
// 0 9 => 5
// 0 4 => 2 6 9 => 7
//0 2 => 1 3 4 => 3 6 7 => 6 8 9 => 8
// 0 1 2 3 4 5 6 7 8 9
int l = 0, r = _MaxUnit;
while(l<r){
int m = (l+r)~/2;
BigDecimal b3 = timesOfDivisor(m);
int comp = b1.compare(b3);
if(comp == 0) return [m,[0]];
//b1 > b3 m可能是结果
if(comp == 1){
if(l+1 == r){
BigDecimal b4 = timesOfDivisor(r);
comp = b1.compare(b4);
if(comp == 0) return [r,[0]];
if(comp == 1) return [r,(b1-b4)._real];
return [l,(b1-b3)._real];
}
l = m;
continue;
}
//b1 < b3 m一定不是结果
if(l+1 == r) return [m,(b1-b3)._real];
r = m - 1;
}
//一定不会执行此语句
return [l,(b1-timesOfDivisor(l))._real];
};
//endregion
//求商
List<int> numDiv = [];
int nRealPrecision = real1.length+dec2.length;
int pPrecision = -nRealPrecision;
List<int> dividend = [];
List<int> divisor = num2;
BigDecimal bdDivisor = BigDecimal.fromReal(num2);
int divMaxBitPrecision = _divMaxPrecision<0?-1:_divMaxPrecision~/9 + (_divMaxPrecision%9==0?0:1);
for(int i=0; i<num1.length||dividend.isNotEmpty; ++i){
if(divMaxBitPrecision>-1){
if(pPrecision>=divMaxBitPrecision) break;
}
// print("#${i.toString().padLeft(4,"0")}: [${dividend.length}]:$dividend");
++pPrecision;
int num = i<num1.length?num1[i]:0;
if(num!=0 || dividend.isNotEmpty) dividend.add(num);
//不够减
if(dividend.length<divisor.length) {
numDiv.add(0);
continue;
}
BigDecimal bdDividend = BigDecimal.fromReal(dividend);
List result = binSub(bdDividend, bdDivisor);
int quotient = result[0];
List<int> remainder = result[1];
numDiv.add(quotient);
if(quotient == 0) continue;
dividend.clear();
dividend.addAll(remainder.skipWhile((e) => e==0).toList());
}
List<int> divReal = numDiv.sublist(0 , nRealPrecision).skipWhile((e) => e==0).toList();
List<int> divDecimal = numDiv.sublist(nRealPrecision);
if(divReal .isEmpty) divReal .add(0);
if(divDecimal.isEmpty) divDecimal.add(0);
//精度对齐
if(_divMaxPrecision>-1&&_divMaxPrecision%9!=0){
int last = divDecimal.last;
int len = _divMaxPrecision%9;
List<int> llast = _splitDecimal(last);
llast = llast.sublist(0, Math.min(llast.length, len));
divDecimal.removeLast();
divDecimal.add(_combineDecimal(llast));
}
for(int i=divDecimal.length-1; i>0; --i){
if(divDecimal[i]==0) divDecimal.removeLast();
else break;
}
return BigDecimal()
.._sign = !(_sign ^ another._sign)
.._nan = false
.._real.clear()
.._real.addAll(divReal)
.._decimal.clear()
.._decimal.addAll(divDecimal);
}
//为了防止计算除法时出现无限小数,设置此位防止死循环
//负数代表不限制
int _divMaxPrecision = 1000;
BigDecimal setDivMaxPrecision(int precision){
_divMaxPrecision = precision;
return this;
}
BigDecimal disablePrecisionLimit(){
_divMaxPrecision = -1;
return this;
}
List<int> real () => __splitReal (_real );
List<int> decimal() => __splitDecimal(_decimal);
BigDecimal _powInternal(int n, Map<int,BigDecimal> mPow){
BigDecimal bd = mPow[n];
if(bd!=null) return bd;
int p1 = n~/2;
int p2 = p1 + (n%2==0?0:1);
BigDecimal bdPow = _powInternal(p1, mPow)*_powInternal(p2, mPow);
mPow[n] = bdPow;
return bdPow.clone();
}
BigDecimal pow(int n){
return _powInternal(n, {0:BigDecimal.one,1:clone()});
}
BigDecimal clone() => BigDecimal()
.._nan = false
.._sign = _sign
.._real.clear()
.._real.addAll(_real)
.._decimal.clear()
.._decimal.addAll(_decimal);
BigDecimal abs(){
return BigDecimal()
.._sign = true
.._nan = _nan
.._real.clear()
.._real.addAll(_real)
.._decimal.clear()
.._decimal.addAll(_decimal);
}
@override
String toString(){
if(_nan) return "nan";
StringBuilder sb = StringBuilder();
if(!_sign) sb.append("-");
sb.append(_real[0].toString());
for(int i=1,ni=_real.length;i<ni;++i){
sb.append(_real[i].toString().padLeft(9,'0'));
}
sb.append(".");
if(_decimal.length>1) {
for(int i=0,ni=_decimal.length-1;i<ni;++i){
sb.append(_decimal[i].toString().padLeft(9,'0'));
}
}
sb.append(_splitDecimal(_decimal[_decimal.length-1]).join());
return sb.toString();
}
@override
int get hashCode => _real.hashCode * _decimal.hashCode;
}
bigdecimal_test.dart
dart
import 'dart:math';
import 'package:flutter_test/flutter_test.dart';
import 'BigDecimal.dart';
import 'StringBuilder.dart';
//region randomGenerate
Random random = Random(DateTime.now().millisecondsSinceEpoch);
String generateNumber({bool decimal=false, int length=0, int maxLength=10000}){
while(length==0) length = random.nextInt(maxLength+1);
StringBuilder sb = StringBuilder();
while(sb.length() < length){
int num = random.nextInt(min(0x7fffffff,pow(10,min(10,length-sb.length()))));
sb.append(num.toString());
}
if(decimal){
if(sb.charAt(sb.length()-1) == "0".codeUnitAt(0)){
int num = random.nextInt(10);
while(num==0) num = random.nextInt(10);
sb.replace(sb.length()-1, sb.length(), num.toString());
}
}
else{
if(sb.charAt(0) == "0".codeUnitAt(0)){
int num = random.nextInt(10);
while(num==0) num = random.nextInt(10);
sb.replace(0, 1, num.toString());
}
}
return sb.toString();
}
//endregion
void main(){
test("BigDecimal constructor test", ()async{
//验证nan
print("Testing NAN");
expect(BigDecimal("nan").toString()=="nan" , isTrue);
//验证1,1E10,1E100,1E1000,1E10000
print("Testing Positive");
expect(BigDecimal("1".padRight(pow(10, 0)+1,"0")).toString(), "1".padRight(pow(10, 0)+1,"0")+".0");
expect(BigDecimal("1".padRight(pow(10, 1)+1,"0")).toString(), "1".padRight(pow(10, 1)+1,"0")+".0");
expect(BigDecimal("1".padRight(pow(10, 2)+1,"0")).toString(), "1".padRight(pow(10, 2)+1,"0")+".0");
expect(BigDecimal("1".padRight(pow(10, 3)+1,"0")).toString(), "1".padRight(pow(10, 3)+1,"0")+".0");
expect(BigDecimal("1".padRight(pow(10, 4)+1,"0")).toString(), "1".padRight(pow(10, 4)+1,"0")+".0");
//验证1E-1,1E-10,1E-100,1E-1000,1E-10000
print("Testing Negative");
expect(BigDecimal("0.${"1".padLeft(pow(10, 0),"0")}").toString(), "0.${"1".padLeft(pow(10, 0),"0")}");
expect(BigDecimal("0.${"1".padLeft(pow(10, 1),"0")}").toString(), "0.${"1".padLeft(pow(10, 1),"0")}");
expect(BigDecimal("0.${"1".padLeft(pow(10, 2),"0")}").toString(), "0.${"1".padLeft(pow(10, 2),"0")}");
expect(BigDecimal("0.${"1".padLeft(pow(10, 3),"0")}").toString(), "0.${"1".padLeft(pow(10, 3),"0")}");
expect(BigDecimal("0.${"1".padLeft(pow(10, 4),"0")}").toString(), "0.${"1".padLeft(pow(10, 4),"0")}");
//随机测验实数和小数长度[1,10000]
print("Testing Random");
for(int i=0;i<10000;++i){
bool sign = random.nextBool();
String real = generateNumber(decimal: false);
String decimal = generateNumber(decimal: true );
String number = "${sign?"":"-"}$real.$decimal";
print("\tEvaluating #${i.toString().padLeft(4)} ${sign?" ":"-"}[${real.length.toString().padLeft(5)}].[${decimal.length.toString().padLeft(5)}]:$number");
expect(BigDecimal(number).toString(), number, reason: "Compare error $i: ${sign?" ":""}$number");
}
print("Test passed!!!");
},timeout: Timeout(Duration(minutes: 1)));
test("BigDecimal compare test", ()async{
expect(BigDecimal("-1").compare(BigDecimal("1" )), -1);
expect(BigDecimal("1" ).compare(BigDecimal("-1")), 1);
expect(BigDecimal("1" ).compare(BigDecimal("1" )), 0);
//Test 99...9 10....0
expect(BigDecimal("9".padLeft (10 ,"9")).compare(BigDecimal("1".padRight(11 ,"0"))), -1);
expect(BigDecimal("1".padRight(11 ,"0")).compare(BigDecimal("9".padLeft (10 ,"9"))), 1);
expect(BigDecimal("9".padLeft (100 ,"9")).compare(BigDecimal("1".padRight(101 ,"0"))), -1);
expect(BigDecimal("1".padRight(101 ,"0")).compare(BigDecimal("9".padLeft (100 ,"9"))), 1);
expect(BigDecimal("9".padLeft (1000 ,"9")).compare(BigDecimal("1".padRight(1001 ,"0"))), -1);
expect(BigDecimal("1".padRight(1001 ,"0")).compare(BigDecimal("9".padLeft (1000 ,"9"))), 1);
expect(BigDecimal("9".padLeft (10000,"9")).compare(BigDecimal("1".padRight(10001,"0"))), -1);
expect(BigDecimal("1".padRight(10001,"0")).compare(BigDecimal("9".padLeft (10000,"9"))), 1);
//Test -99...9 -10....0
expect(BigDecimal("-${"9".padLeft (10 ,"9")}").compare(BigDecimal("-${"1".padRight(11 ,"0")}")), 1);
expect(BigDecimal("-${"1".padRight(11 ,"0")}").compare(BigDecimal("-${"9".padLeft (10 ,"9")}")), -1);
expect(BigDecimal("-${"9".padLeft (100 ,"9")}").compare(BigDecimal("-${"1".padRight(101 ,"0")}")), 1);
expect(BigDecimal("-${"1".padRight(101 ,"0")}").compare(BigDecimal("-${"9".padLeft (100 ,"9")}")), -1);
expect(BigDecimal("-${"9".padLeft (1000 ,"9")}").compare(BigDecimal("-${"1".padRight(1001 ,"0")}")), 1);
expect(BigDecimal("-${"1".padRight(1001 ,"0")}").compare(BigDecimal("-${"9".padLeft (1000 ,"9")}")), -1);
expect(BigDecimal("-${"9".padLeft (10000,"9")}").compare(BigDecimal("-${"1".padRight(10001,"0")}")), 1);
expect(BigDecimal("-${"1".padRight(10001,"0")}").compare(BigDecimal("-${"9".padLeft (10000,"9")}")), -1);
//Test random
for(int i=0; i<10000; ++i){
bool sign1 = random.nextBool();
String strReal1 = generateNumber(decimal: false);
String strDecimal1 = generateNumber(decimal: true );
String number1 = "${sign1?"":"-"}$strReal1.$strDecimal1";
bool sign2 = random.nextBool();
String strReal2 = generateNumber(decimal: false);
String strDecimal2 = generateNumber(decimal: true );
String number2 = "${sign2?"":"-"}$strReal2.$strDecimal2";
int compare;
if( sign1 && !sign2) compare = 1;
if(!sign1 && sign2) compare = -1;
if(sign1 == sign2){
bool sign = sign1;
if (strReal1.length>strReal2.length) compare = 1;
else if(strReal1.length<strReal2.length) compare = -1;
else compare = strReal1.compareTo(strReal2);
if(compare==0){
String strDecimal3 = strDecimal1.padRight(max(strDecimal1.length, strDecimal2.length),"0");
String strDecimal4 = strDecimal2.padRight(max(strDecimal1.length, strDecimal2.length),"0");
compare = strDecimal3.compareTo(strDecimal4);
}
if(compare!=0){
compare = sign ? compare : -compare;
}
}
expect(BigDecimal(number1).compare(BigDecimal(number2)), compare);
}
});
test("BigDecimal operator + test", ()async{
print("Testing Basic");
expect((BigDecimal("1" )+BigDecimal("1" )).toString(), BigDecimal("2" ).toString());
expect((BigDecimal("-1")+BigDecimal("1" )).toString(), BigDecimal.zero .toString());
expect((BigDecimal("-1")+BigDecimal("-1")).toString(), BigDecimal("-2").toString());
print("Testing Real");
expect((BigDecimal("9".padLeft (10 ,"9"))+BigDecimal.one).toString(), BigDecimal("1".padRight(11 ,"0")).toString());
expect((BigDecimal("9".padLeft (100 ,"9"))+BigDecimal.one).toString(), BigDecimal("1".padRight(101 ,"0")).toString());
expect((BigDecimal("9".padLeft (1000 ,"9"))+BigDecimal.one).toString(), BigDecimal("1".padRight(1001 ,"0")).toString());
expect((BigDecimal("9".padLeft (10000,"9"))+BigDecimal.one).toString(), BigDecimal("1".padRight(10001,"0")).toString());
print("Testing Decimal");
expect((BigDecimal("0.${"1".padLeft(pow(10, 0),"0")}")+BigDecimal("0.${"9".padLeft(pow(10, 0),"9")}")).toString(), BigDecimal.one.toString());
expect((BigDecimal("0.${"1".padLeft(pow(10, 1),"0")}")+BigDecimal("0.${"9".padLeft(pow(10, 1),"9")}")).toString(), BigDecimal.one.toString());
expect((BigDecimal("0.${"1".padLeft(pow(10, 2),"0")}")+BigDecimal("0.${"9".padLeft(pow(10, 2),"9")}")).toString(), BigDecimal.one.toString());
expect((BigDecimal("0.${"1".padLeft(pow(10, 3),"0")}")+BigDecimal("0.${"9".padLeft(pow(10, 3),"9")}")).toString(), BigDecimal.one.toString());
expect((BigDecimal("0.${"1".padLeft(pow(10, 4),"0")}")+BigDecimal("0.${"9".padLeft(pow(10, 4),"9")}")).toString(), BigDecimal.one.toString());
print("Testing random");
for(int i=0; i<10000; ++i) {
print("\tEvaluating #${i.toString().padLeft(4)} ->");
String strReal1 = generateNumber(decimal: false);
String strDecimal1 = generateNumber(decimal: true);
String number1 = "$strReal1.$strDecimal1";
String strReal2 = generateNumber(decimal: false);
String strDecimal2 = generateNumber(decimal: true);
String number2 = "$strReal2.$strDecimal2";
print("\t\t[${strReal1.length.toString().padLeft(5)}].[${strDecimal1.length.toString().padLeft(5)}]:${strReal1.padLeft(max(strReal1.length, strReal2.length)," ")}.$strDecimal1");
print("\t\t[${strReal2.length.toString().padLeft(5)}].[${strDecimal2.length.toString().padLeft(5)}]:${strReal2.padLeft(max(strReal1.length, strReal2.length)," ")}.$strDecimal2");
BigInt biReal1 = BigInt.parse(strReal1 );
BigInt biDecimal1 = BigInt.parse(strDecimal1.padRight(max(strDecimal1.length, strDecimal2.length),"0"));
BigInt biReal2 = BigInt.parse(strReal2 );
BigInt biDecimal2 = BigInt.parse(strDecimal2.padRight(max(strDecimal1.length, strDecimal2.length),"0"));
BigInt biDecimal3 = biDecimal1 + biDecimal2;
String strDecimal3 = biDecimal3.toString();
bool carry = max(strDecimal1.length, strDecimal2.length) != strDecimal3.length;
BigInt biReal3 = biReal1 + biReal2 + (carry?BigInt.one : BigInt.zero);
String strReal3 = biReal3.toString();
if(carry) strDecimal3 = strDecimal3.substring(1);
expect(BigDecimal(number1)+BigDecimal(number2), BigDecimal("$strReal3.$strDecimal3"));
}
});
test("BigDecimal operator - test",()async{
print("Testing Basic");
expect((BigDecimal("1" )-BigDecimal("1" )).toString(), BigDecimal.zero .toString());
expect((BigDecimal("2" )-BigDecimal("1" )).toString(), BigDecimal.one .toString());
expect((BigDecimal.zero -BigDecimal("1" )).toString(), BigDecimal("-1").toString());
print("Testing Real");
expect((BigDecimal("1".padRight(11 ,"0"))-BigDecimal.one).toString(), BigDecimal("9".padLeft (10 ,"9")).toString());
expect((BigDecimal("1".padRight(101 ,"0"))-BigDecimal.one).toString(), BigDecimal("9".padLeft (100 ,"9")).toString());
expect((BigDecimal("1".padRight(1001 ,"0"))-BigDecimal.one).toString(), BigDecimal("9".padLeft (1000 ,"9")).toString());
expect((BigDecimal("1".padRight(10001,"0"))-BigDecimal.one).toString(), BigDecimal("9".padLeft (10000,"9")).toString());
print("Testing Decimal");
expect((BigDecimal.one-BigDecimal("0.${"1".padLeft(pow(10, 0),"0")}")).toString(), BigDecimal("0.${"9".padLeft(pow(10, 0),"9")}").toString());
expect((BigDecimal.one-BigDecimal("0.${"1".padLeft(pow(10, 1),"0")}")).toString(), BigDecimal("0.${"9".padLeft(pow(10, 1),"9")}").toString());
expect((BigDecimal.one-BigDecimal("0.${"1".padLeft(pow(10, 2),"0")}")).toString(), BigDecimal("0.${"9".padLeft(pow(10, 2),"9")}").toString());
expect((BigDecimal.one-BigDecimal("0.${"1".padLeft(pow(10, 3),"0")}")).toString(), BigDecimal("0.${"9".padLeft(pow(10, 3),"9")}").toString());
expect((BigDecimal.one-BigDecimal("0.${"1".padLeft(pow(10, 4),"0")}")).toString(), BigDecimal("0.${"9".padLeft(pow(10, 4),"9")}").toString());
print("Testing random");
for(int i=0; i<1000; ++i) {
print("\tEvaluating #${i.toString().padLeft(4)} ->");
String strReal1 = generateNumber(decimal: false);
String strDecimal1 = generateNumber(decimal: true);
String number1 = "$strReal1.$strDecimal1";
String strReal2 = generateNumber(decimal: false);
String strDecimal2 = generateNumber(decimal: true);
String number2 = "$strReal2.$strDecimal2";
print("\t\t[${strReal1.length.toString().padLeft(5)}].[${strDecimal1.length.toString().padLeft(5)}]:${strReal1.padLeft(max(strReal1.length, strReal2.length)," ")}.$strDecimal1");
print("\t\t[${strReal2.length.toString().padLeft(5)}].[${strDecimal2.length.toString().padLeft(5)}]:${strReal2.padLeft(max(strReal1.length, strReal2.length)," ")}.$strDecimal2");
BigInt biReal1 = BigInt.parse(strReal1 );
BigInt biDecimal1 = BigInt.parse(strDecimal1.padRight(max(strDecimal1.length, strDecimal2.length),"0"));
BigInt biReal2 = BigInt.parse(strReal2 );
BigInt biDecimal2 = BigInt.parse(strDecimal2.padRight(max(strDecimal1.length, strDecimal2.length),"0"));
int compare;
if (strReal1.length>strReal2.length) compare = 1;
else if(strReal1.length<strReal2.length) compare = -1;
else compare = strReal1.compareTo(strReal2);
if(compare==0){
String strDecimal3 = strDecimal1.padRight(max(strDecimal1.length, strDecimal2.length),"0");
String strDecimal4 = strDecimal2.padRight(max(strDecimal1.length, strDecimal2.length),"0");
compare = strDecimal3.compareTo(strDecimal4);
}
BigInt biDecimal3 = BigInt.zero;
String strReal3 = "";
String strDecimal3 = "";
if(compare==1){
biDecimal3 = biDecimal1 - biDecimal2;
bool borrow = biDecimal3 < BigInt.zero;
BigInt biReal3 = biReal1 - biReal2 - (borrow?BigInt.one : BigInt.zero);
strReal3 = biReal3.toString();
if(borrow) strDecimal3 = (biDecimal3 + BigInt.parse("1".padRight(max(strDecimal1.length, strDecimal2.length)+1,"0"))).toString();
else strDecimal3 = biDecimal3.toString();
}
if(compare==-1){// a-b = -(b-a)
biDecimal3 = biDecimal2 - biDecimal1;
bool borrow = biDecimal3 < BigInt.zero;
BigInt biReal3 = biReal2 - biReal1 - (borrow?BigInt.one : BigInt.zero);
strReal3 = "-"+biReal3.toString();
if(borrow) strDecimal3 = (biDecimal3 + BigInt.parse("1".padRight(max(strDecimal1.length, strDecimal2.length)+1,"0"))).toString();
else strDecimal3 = biDecimal3.toString();
}
if(strDecimal3 != "0"){
strDecimal3 = strDecimal3.padLeft(max(strDecimal1.length, strDecimal2.length),"0");
while(strDecimal3.length>0){
if(strDecimal3.substring(strDecimal3.length-1) == "0"){
strDecimal3 = strDecimal3.substring(0, strDecimal3.length-1);
continue;
}
break;
}
}
expect(BigDecimal(number1)-BigDecimal(number2), BigDecimal("$strReal3.$strDecimal3"));
}
});
test("BigDecimal operator * test",()async{
print("Testing Basic");
expect((BigDecimal("1" )*BigDecimal("1" )).toString(), BigDecimal("1" ).toString());
expect((BigDecimal("-1")*BigDecimal("1" )).toString(), BigDecimal("-1").toString());
expect((BigDecimal("-1")*BigDecimal("-1")).toString(), BigDecimal("1" ).toString());
print("Testing Real");
expect((BigDecimal("9".padLeft (10 ,"9"))*BigDecimal.one).toString(), BigDecimal("9".padLeft (10 ,"9")).toString());
expect((BigDecimal("9".padLeft (100 ,"9"))*BigDecimal.one).toString(), BigDecimal("9".padLeft (100 ,"9")).toString());
expect((BigDecimal("9".padLeft (1000 ,"9"))*BigDecimal.one).toString(), BigDecimal("9".padLeft (1000 ,"9")).toString());
expect((BigDecimal("9".padLeft (10000,"9"))*BigDecimal.one).toString(), BigDecimal("9".padLeft (10000,"9")).toString());
print("Testing Decimal");
expect((BigDecimal("0.${"9".padLeft(pow(10, 0),"9")}")*BigDecimal.one).toString(), BigDecimal("0.${"9".padLeft(pow(10, 0),"9")}").toString());
expect((BigDecimal("0.${"9".padLeft(pow(10, 1),"9")}")*BigDecimal.one).toString(), BigDecimal("0.${"9".padLeft(pow(10, 1),"9")}").toString());
expect((BigDecimal("0.${"9".padLeft(pow(10, 2),"9")}")*BigDecimal.one).toString(), BigDecimal("0.${"9".padLeft(pow(10, 2),"9")}").toString());
expect((BigDecimal("0.${"9".padLeft(pow(10, 3),"9")}")*BigDecimal.one).toString(), BigDecimal("0.${"9".padLeft(pow(10, 3),"9")}").toString());
expect((BigDecimal("0.${"9".padLeft(pow(10, 4),"9")}")*BigDecimal.one).toString(), BigDecimal("0.${"9".padLeft(pow(10, 4),"9")}").toString());
print("Testing random");
for(int i=0; i<10000; ++i) {
print("\tEvaluating #${i.toString().padLeft(4)} ->");
String strReal1 = generateNumber(decimal: false);
String strDecimal1 = generateNumber(decimal: true);
String number1 = "$strReal1.$strDecimal1";
String strReal2 = generateNumber(decimal: false);
String strDecimal2 = generateNumber(decimal: true);
String number2 = "$strReal2.$strDecimal2";
print("\t\t[${strReal1.length.toString().padLeft(5)}].[${strDecimal1.length.toString().padLeft(5)}]:${strReal1.padLeft(max(strReal1.length, strReal2.length)," ")}.$strDecimal1");
print("\t\t[${strReal2.length.toString().padLeft(5)}].[${strDecimal2.length.toString().padLeft(5)}]:${strReal2.padLeft(max(strReal1.length, strReal2.length)," ")}.$strDecimal2");
BigInt biNum1 = BigInt.parse("$strReal1${strDecimal1.padRight(max(strDecimal1.length, strDecimal2.length),"0")}");
BigInt biNum2 = BigInt.parse("$strReal2${strDecimal2.padRight(max(strDecimal1.length, strDecimal2.length),"0")}");
BigInt biPow = BigInt.parse("1".padRight(max(strDecimal1.length,strDecimal2.length)*2+1,"0"));
BigInt biNum3 = biNum1 * biNum2;
String strReal3 = (biNum3~/biPow).toString();
String strDecimal3 = (biNum3%biPow).toString().padLeft(max(strDecimal1.length, strDecimal2.length)*2,"0");
while(strDecimal3.length>0){
if(strDecimal3.substring(strDecimal3.length-1) == "0"){
strDecimal3 = strDecimal3.substring(0, strDecimal3.length-1);
continue;
}
break;
}
expect(BigDecimal(number1)*BigDecimal(number2), BigDecimal("$strReal3.$strDecimal3"));
}
print("Test Passed");
});
test("BigDecimal operator / test",()async{
print("Testing Basic");
expect((BigDecimal("1" ).disablePrecisionLimit()/BigDecimal("0.1" )).toString(), BigDecimal("10").toString());
expect((BigDecimal("1" ).disablePrecisionLimit()/BigDecimal("1" )).toString(), BigDecimal("1" ).toString());
expect((BigDecimal("-1").disablePrecisionLimit()/BigDecimal("1" )).toString(), BigDecimal("-1").toString());
expect((BigDecimal("-1").disablePrecisionLimit()/BigDecimal("-1" )).toString(), BigDecimal("1" ).toString());
print("Testing Real");
expect((BigDecimal("9".padLeft (10 ,"9")).disablePrecisionLimit()/BigDecimal.one).toString(), BigDecimal("9".padLeft (10 ,"9")).toString());
expect((BigDecimal("9".padLeft (100 ,"9")).disablePrecisionLimit()/BigDecimal.one).toString(), BigDecimal("9".padLeft (100 ,"9")).toString());
expect((BigDecimal("9".padLeft (1000 ,"9")).disablePrecisionLimit()/BigDecimal.one).toString(), BigDecimal("9".padLeft (1000 ,"9")).toString());
expect((BigDecimal("9".padLeft (10000,"9")).disablePrecisionLimit()/BigDecimal.one).toString(), BigDecimal("9".padLeft (10000,"9")).toString());
print("Testing Decimal");
expect((BigDecimal("0.${"9".padLeft(pow(10, 0),"9")}").disablePrecisionLimit()/BigDecimal.one).toString(), BigDecimal("0.${"9".padLeft(pow(10, 0),"9")}").toString());
expect((BigDecimal("0.${"9".padLeft(pow(10, 1),"9")}").disablePrecisionLimit()/BigDecimal.one).toString(), BigDecimal("0.${"9".padLeft(pow(10, 1),"9")}").toString());
expect((BigDecimal("0.${"9".padLeft(pow(10, 2),"9")}").disablePrecisionLimit()/BigDecimal.one).toString(), BigDecimal("0.${"9".padLeft(pow(10, 2),"9")}").toString());
expect((BigDecimal("0.${"9".padLeft(pow(10, 3),"9")}").disablePrecisionLimit()/BigDecimal.one).toString(), BigDecimal("0.${"9".padLeft(pow(10, 3),"9")}").toString());
expect((BigDecimal("0.${"9".padLeft(pow(10, 4),"9")}").disablePrecisionLimit()/BigDecimal.one).toString(), BigDecimal("0.${"9".padLeft(pow(10, 4),"9")}").toString());
print("Testing random");
for(int i=0; i<1000; ++i) {
print("\tEvaluating #${i.toString().padLeft(4)} ->");
String strReal1 = generateNumber(decimal: false, maxLength: 50);
String strDecimal1 = generateNumber(decimal: true , maxLength: 50);
String number1 = "$strReal1.$strDecimal1";
String strReal2 = generateNumber(decimal: false, maxLength: 50);
String strDecimal2 = generateNumber(decimal: true , maxLength: 50);
String number2 = "$strReal2.$strDecimal2";
print("\t\t[${strReal1.length.toString().padLeft(5)}].[${strDecimal1.length.toString().padLeft(5)}]:${strReal1.padLeft(max(strReal1.length, strReal2.length)," ")}.$strDecimal1");
print("\t\t[${strReal2.length.toString().padLeft(5)}].[${strDecimal2.length.toString().padLeft(5)}]:${strReal2.padLeft(max(strReal1.length, strReal2.length)," ")}.$strDecimal2");
StringBuilder sbDiv = StringBuilder();
int nRealBitPrecision = strReal1.length + strDecimal2.length;
int pPrecision = -nRealBitPrecision;
int char0 = "0".codeUnitAt(0);
BigInt biTen = BigInt.from(10);
String strNum1 = "$strReal1$strDecimal1";
BigInt dividend = BigInt.zero;
BigInt divisor = BigInt.parse("$strReal2$strDecimal2");
for(int i=0; i<strNum1.length || dividend!=BigInt.zero; ++i){
if(pPrecision++>=1000) break;
int num = i<strNum1.length ? (strNum1.codeUnitAt(i)-char0) : 0;
dividend = dividend*biTen + BigInt.from(num);
if(dividend<divisor){
sbDiv.append(0);
continue;
}
BigInt quotient = dividend~/divisor;
BigInt remainder = dividend%divisor;
sbDiv.append(quotient.toString());
dividend = remainder;
}
String strReal3 = sbDiv.substring(0 , nRealBitPrecision);
String strDecimal3 = sbDiv.substring(nRealBitPrecision);
while(strReal3.length>0){
if(strReal3.substring(0,1) == "0"){
strReal3 = strReal3.substring(1);
continue;
}
break;
}
while(strDecimal3.length>0){
if(strDecimal3.substring(strDecimal3.length-1) == "0"){
strDecimal3 = strDecimal3.substring(0, strDecimal3.length-1);
continue;
}
break;
}
expect(BigDecimal(number1)/BigDecimal(number2), BigDecimal("$strReal3.$strDecimal3"));
}
print("Test Passed");
});
test("BigDecimal operator / test 2",()async{
print("Testing Basic");
expect((BigDecimal("1" ).disablePrecisionLimit()/BigDecimal("0.1" )).toString(), BigDecimal("10").toString());
expect((BigDecimal("1" ).disablePrecisionLimit()/BigDecimal("1" )).toString(), BigDecimal("1" ).toString());
expect((BigDecimal("-1").disablePrecisionLimit()/BigDecimal("1" )).toString(), BigDecimal("-1").toString());
expect((BigDecimal("-1").disablePrecisionLimit()/BigDecimal("-1" )).toString(), BigDecimal("1" ).toString());
print("Testing Real");
expect((BigDecimal("9".padLeft (10 ,"9")).disablePrecisionLimit()/BigDecimal.one).toString(), BigDecimal("9".padLeft (10 ,"9")).toString());
expect((BigDecimal("9".padLeft (100 ,"9")).disablePrecisionLimit()/BigDecimal.one).toString(), BigDecimal("9".padLeft (100 ,"9")).toString());
expect((BigDecimal("9".padLeft (1000 ,"9")).disablePrecisionLimit()/BigDecimal.one).toString(), BigDecimal("9".padLeft (1000 ,"9")).toString());
expect((BigDecimal("9".padLeft (10000,"9")).disablePrecisionLimit()/BigDecimal.one).toString(), BigDecimal("9".padLeft (10000,"9")).toString());
print("Testing Decimal");
expect((BigDecimal("0.${"9".padLeft(pow(10, 0),"9")}").disablePrecisionLimit()/BigDecimal.one).toString(), BigDecimal("0.${"9".padLeft(pow(10, 0),"9")}").toString());
expect((BigDecimal("0.${"9".padLeft(pow(10, 1),"9")}").disablePrecisionLimit()/BigDecimal.one).toString(), BigDecimal("0.${"9".padLeft(pow(10, 1),"9")}").toString());
expect((BigDecimal("0.${"9".padLeft(pow(10, 2),"9")}").disablePrecisionLimit()/BigDecimal.one).toString(), BigDecimal("0.${"9".padLeft(pow(10, 2),"9")}").toString());
expect((BigDecimal("0.${"9".padLeft(pow(10, 3),"9")}").disablePrecisionLimit()/BigDecimal.one).toString(), BigDecimal("0.${"9".padLeft(pow(10, 3),"9")}").toString());
expect((BigDecimal("0.${"9".padLeft(pow(10, 4),"9")}").disablePrecisionLimit()/BigDecimal.one).toString(), BigDecimal("0.${"9".padLeft(pow(10, 4),"9")}").toString());
print("Testing random");
for(int i=0; i<10000; ++i) {
print("\tEvaluating #${i.toString().padLeft(4)} ->");
String strReal1 = generateNumber(decimal: false, maxLength: 50);
String strDecimal1 = generateNumber(decimal: true, maxLength: 50);
String number1 = "$strReal1.$strDecimal1";
String strReal2 = generateNumber(decimal: false, maxLength: 50);
String strDecimal2 = generateNumber(decimal: true, maxLength: 50);
String number2 = "$strReal2.$strDecimal2";
print("\t\t[${strReal1.length.toString().padLeft(5)}].[${strDecimal1.length.toString().padLeft(5)}]:${strReal1.padLeft(max(strReal1.length, strReal2.length)," ")}.$strDecimal1");
print("\t\t[${strReal2.length.toString().padLeft(5)}].[${strDecimal2.length.toString().padLeft(5)}]:${strReal2.padLeft(max(strReal1.length, strReal2.length)," ")}.$strDecimal2");
BigDecimal bd1 = BigDecimal(number1);
BigDecimal bd2 = BigDecimal(number2);
BigDecimal bd3 = bd1*bd2;
expect(bd3.disablePrecisionLimit()/bd2, bd1);
}
print("Test Passed");
},);
}