/** @format */ // ---------Math----------- interface Math { /** * 返回[min,max]闭区间随机整数 * @param min 最小值 * @param max 最大值 * @param seed 随机种子 */ randomRangeInt(min: number, max: number, seed?: number): number /** * 返回[min,max]闭区间随机浮点数 * @param min 最小值 * @param max 最大值 * @param seed 随机种子 */ randomRangeFloat(min: number, max: number, seed?: number): number /** * 返回[min,max]闭区间随机整数数组 * @param min 最小值 * @param max 最大值 * @param count 数量 * @param seed 随机种子 */ randomRangeIntArr(min: number, max: number, count: number, seed?: number): number[] /** * 返回余数 * @param x 除数 * @param y 被除数 */ fMod(x: number, y: number): number /** * 返回正态分布随机数 * @param mean 基数 * @param stdDev 标准差 */ getNumberInNormalDistribution(mean, stdDev) randomNormalDistribution() /** * 给一个数添加前导0 * @param num 数字 * @param length 包含数字的位数 */ addPreZero(num: number, length: number) /** * 给定圆心坐标和圆的半径,获得一个圆内的随机点 * @param pos 圆心 * @param radius 半径 */ getCirclesRandPos(pos: cc.Vec2, radius: number) /** * 获取一个概率是否成功 * @param val 0 - 1 */ getProb(val: number, seed?: number) /** * 判断阿拉伯数字转换成中文 * @param num 阿拉伯数字 * @return 对应中文 */ toBigTextNum(num: Number): string // 判断一个整数是否在安全的范围 isSafeInteger(n: number) /** * 将数字转换为带有 K、M、B 等后缀的字符串 * @param num 数字 * @return 对应字符串 */ toKMBNum(num: Number): string /** * 限制数字再指定范围内,如果超出范围,则返回边界值 * @param value * @param min * @param max */ clampValue(value: number, min: number, max: number): number /** * 获取目标数二进制最后一位开始某个位置的数字是0还是1的布尔值 * @param target * @param index */ getBitBool(target: number, index: number): boolean /* * 是否开启伪随机 */ isSeededRandom: boolean /* * 随机种子 */ seed: number } Math.isSeededRandom = false Math.seed = Date.now() Math.randomRangeInt = (min: number, max: number, seed: number): number => { let rand = Math.random() if (seed || Math.isSeededRandom) { rand = createRandom(seed) } if (rand === 1) { rand -= Number.EPSILON } return min + Math.floor(rand * (max - min + 1)) } Math.randomRangeFloat = (min: number, max: number, seed: number): number => { let rand = Math.random() if (seed || Math.isSeededRandom) { rand = createRandom(seed) } return min + rand * (max - min) } Math.randomRangeIntArr = (min: number, max: number, count: number, seed: number): number[] => { if (count > max - min + 1) { return [] } let tempArr = [] for (let i = min; i <= max; i++) { tempArr.push(i) } let newArrList = [] for (let i = 0; i < count; i++) { let baseRandom = Math.random() if (seed || Math.isSeededRandom) { baseRandom = createRandom(seed) } let random = Math.floor(baseRandom * tempArr.length) let value = tempArr[random] tempArr.splice(random, 1) newArrList.push(value) } return newArrList } Math.fMod = (x: number, y: number): number => { const temp = Math.floor(x / y) return x - temp * y } Math.getNumberInNormalDistribution = (mean, stdDev) => mean + Math.randomNormalDistribution() * stdDev Math.randomNormalDistribution = () => { let u = 0.0 let v = 0.0 let w = 0.0 let c = 0.0 do { // 获得两个(-1,1)的独立随机变量 u = Math.random() * 2 - 1.0 v = Math.random() * 2 - 1.0 w = u * u + v * v } while (w == 0.0 || w >= 1.0) // 这里就是 Box-Muller转换 c = Math.sqrt((-2 * Math.log(w)) / w) // 返回2个标准正态分布的随机数,封装进一个数组返回 // 当然,因为这个函数运行较快,也可以扔掉一个 // return [u*c,v*c]; return u * c } Math.addPreZero = (num: number, length: number) => { let numstr = num.toString() const l = numstr.length if (numstr.length >= length) { return numstr } for (let i = 0; i < length - l; i++) { numstr = `0${numstr}` } return numstr } Math.getCirclesRandPos = (pos: cc.Vec2, radius: number) => { const r = radius * Math.sqrt(Math.random()) const theta = Math.random() * 2 * Math.PI return cc.v2(pos.x + r * Math.cos(theta), pos.y + r * Math.sin(theta)) } Math.getProb = (val: number, seed: number) => { if (val == 0) { return false } const probability = val * 100 || 1 let rand = Math.random() if (seed || Math.isSeededRandom) { rand = createRandom(seed) } const odds = Math.floor(rand * 100) if (probability === 1 && val != 0.01) { return true } if (odds < probability) { return true } return false } Math.toBigTextNum = (num: number) => { const chnNumChar = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九'] const chnUnitSection = ['', '万', '亿', '万亿', '亿亿'] const chnUnitChar = ['', '十', '百', '千'] const SectionToChinese = section => { let strIns = '' let chnStr = '' let unitPos = 0 let zero = true while (section > 0) { const v = section % 10 if (v === 0) { if (!zero) { zero = true chnStr = chnNumChar[v] + chnStr } } else { zero = false strIns = chnNumChar[v] strIns += chnUnitChar[unitPos] chnStr = strIns + chnStr } unitPos++ section = Math.floor(section / 10) } return chnStr } let unitPos = 0 let strIns = '' let chnStr = '' let needZero = false if (num === 0) { return chnNumChar[0] } while (num > 0) { const section = num % 10000 if (needZero) { chnStr = chnNumChar[0] + chnStr } strIns = SectionToChinese(section) strIns += section !== 0 ? chnUnitSection[unitPos] : chnUnitSection[0] chnStr = strIns + chnStr needZero = section < 1000 && section > 0 num = Math.floor(num / 10000) unitPos++ } return chnStr } Math.isSafeInteger = n => typeof n === 'number' && // 判断是否是一个数字类型 Math.round(n) === n && // 判断是否是整数,Math.round()方法用于取整 Number.MIN_SAFE_INTEGER <= n && // 判断是否大于最小整数 n <= Number.MAX_SAFE_INTEGER // 判断是否小于最大整数 let createRandom = seed => { if (!seed) { Math.seed += 1 seed = Math.seed } let x = Math.sin(seed) * 10000 return x - Math.floor(x) } Math.toKMBNum = (num: number): string => { const suffixes = ['', 'K', 'M', 'B', 'T'] let suffixIndex = 0 let origin = num while (num >= 1000 && suffixIndex < suffixes.length - 1) { num /= 1000 suffixIndex++ } return origin < 1000 ? String(num.toFixed(0)) : num.toFixed(2) + suffixes[suffixIndex] } Math.clampValue = (value: number, min: number, max: number): number => { return value < min ? min : value > max ? max : value } Math.getBitBool = (target: number, index: number): boolean => { return (target & (1 << index)) !== 0 }