declare interface Number {
    
    /**
     * 金額每三位數(千)加逗號, 並且補到小數點第2位
     * 輸出 41,038,560.00  
     * @param precision 補到小數點第幾位
     * @param isPadZero 是否要補零
     * */
    ExFormatNumberWithComma(precision?: number, isPadZero?: boolean): string;
    /**
     * 基本4位數(9,999-999B-T)
     * */
    ExTransferToBMK(precision?: number,offset?: number): string;
    /**
     * 數字轉字串, 頭補0
     * @param size 
     */
    Pad(size: number): string;
    /**
     * 四捨五入到小數點第X位 (同server計算規則)
     * @param precision 
     */
    ExToNumRoundDecimal(precision: number): number;
    /**
     * 無條件捨去到小數點第X位
     * @param precision 
     */
    ExToNumFloorDecimal(precision: number): number;
    /**
     * 無條件捨去強制保留X位小數,如:2,會在2後面補上00.即2.00 
     * @param precision 補到小數點第幾位
     * @param isPadZero 是否要補零
     */
    ExToStringFloorDecimal(precision: number, isPadZero?: boolean): string;
    /**
     * 取整數)
     */
    ExToInt():number;
    /**
     * 小數轉整數(支援科學符號)
     */
    Float2Fixed():number;
    /**
     * 數字長度(支援科學符號)
     */
    DigitLength():number;

    target: number;

   
}

Number.prototype.ExFormatNumberWithComma || Object.defineProperty(Number.prototype, 'ExFormatNumberWithComma', {
    enumerable: false,
    value: function (precision: number = 2, isPadZero: boolean = true) {
           
        // let arr = String(this).split('.');
        let arr = this.ExToStringFloorDecimal(precision, isPadZero).split('.');
        let num = arr[0], result = '';
        while (num.length > 3) {
            result = ',' + num.slice(-3) + result;
            num = num.slice(0, num.length - 3);
        }
        if (num.length > 0) result = num + result;
        return arr[1] ? result + '.' + arr[1] : result;
    }
})


Number.prototype.ExTransferToBMK || Object.defineProperty(Number.prototype, 'ExTransferToBMK', {
    enumerable: false,
    value: function (precision: number=2,offset: number = 0) {
        /**千 */
        let MONEY_1K: number = 1000;
        /**萬 */
        // let MONEY_10K: number = 10000;
        /**十萬 */
        // let MONEY_100K: number = 100000;
        /**百萬 */
        let MONEY_1M: number = 1000000;
        /**千萬 */
        // let MONEY_10M: number = 10000000;
        /**億 */
        // let MONEY_100M: number = 100000000;
        /**十億 */
        let MONEY_1B: number = 1000000000;
        /**百億 */
        // let MONEY_10B: number = 10000000000;
        /**千億 */
        // let MONEY_100B: number = 100000000000;
        /**兆 */
        // let MONEY_1T: number = 1000000000000;
        offset = Math.pow(10, offset);
        // if (this >= MONEY_1T * offset) {
        //     //(3)1,000T
        //     //1T~
        //     return (~~(this / MONEY_1T)).ExFormatNumberWithComma(0) + "T";
        // }
        if (this >= MONEY_1B * offset) {
            //1,000B~900,000B
            //1B~900B
            return (this / MONEY_1B).ExFormatNumberWithComma(3, false) + "B";
        }
        else if (this >= MONEY_1M * offset) {
            //1,000M~900,000M
            //1M~900M
            return (this / MONEY_1M).ExFormatNumberWithComma(3, false) + "M";
        }
        else if (this >= MONEY_1K * offset) {
            //1,000K~900,000K
            //1K~90K
            return (this / MONEY_1K).ExFormatNumberWithComma(3, false) + "K";
        }
        else {
            //0~9,000,000
            //0~9,000
            return this.ExFormatNumberWithComma(precision);
        }
    }
})
Number.prototype.Pad || Object.defineProperty(Number.prototype, 'Pad', {
    enumerable: false,
    value: function (size: number) {
        let s = this + "";
        while (s.length < size) s = "0" + s;
        return s;
    }
})
Number.prototype.ExToNumRoundDecimal || Object.defineProperty(Number.prototype, 'ExToNumRoundDecimal', {
    enumerable: false,
    value: function (precision: number) {
        return Math.round(Math.round(this * Math.pow(10, (precision || 0) + 1)) / 10) / Math.pow(10, (precision || 0));
    }
})
Number.prototype.ExToInt || Object.defineProperty(Number.prototype, 'ExToInt',{
    enumerable: false,
    value: function (){
        return ~~this;
    }
})
Number.prototype.ExToNumFloorDecimal || Object.defineProperty(Number.prototype, 'ExToNumFloorDecimal', {
    enumerable: false,
    value: function (precision: number) { 
        let str = this.toPrecision(12);
        let dotPos = str.indexOf('.');
        return dotPos == -1 ? this : +`${str.substr(0, dotPos + 1 + precision)}`;
    }
})
Number.prototype.ExToStringFloorDecimal || Object.defineProperty(Number.prototype, 'ExToStringFloorDecimal', {
    enumerable: false,
    value: function (precision: number, isPadZero: boolean = true) {
        // 取小數點第X位
        let f = this.ExToNumFloorDecimal(precision);
        let s = f.toString();
        // 補0
        if (isPadZero) {
            let rs = s.indexOf('.');
            if (rs < 0) {
                rs = s.length;
                s += '.';
            }
            while (s.length <= rs + precision) {
                s += '0';
            }
        }
        return s;
    }
})
Number.prototype.Float2Fixed || Object.defineProperty(Number.prototype, 'Float2Fixed', {
    enumerable: false,
    value: function () {
        if (this.toString().indexOf('e') === -1) {
        return Number(this.toString().replace('.', ''));
        }
        const dLen = this.DigitLength();
        return dLen > 0 ? +parseFloat((this * Math.pow(10, dLen)).toPrecision(12)) : this;
    }
})
Number.prototype.DigitLength || Object.defineProperty(Number.prototype, 'DigitLength', {
    enumerable: false,
    value: function () {
        const eSplit = this.toString().split(/[eE]/);
        const len = (eSplit[0].split('.')[1] || '').length - (+(eSplit[1] || 0));
        return len > 0 ? len : 0;
    }
})