Flutter放置游戏自定义大数类sub函数崩溃问题求助
Flutter放置游戏数值减法函数冻结问题修复
问题根源分析
你的sub函数导致模拟器冻结的核心原因是无限循环,具体问题点:
- 借位逻辑错误:你的
fixNum函数中,数值≥94868330时触发进位,说明每一位的基数是94868330,但原代码借位时给当前位加94868329,少加了1,导致借位后当前位仍可能小于减数位,触发无限循环。 - 高位借位未处理零值:当
numbs[i+1]本身为0时,numbs[i+1]-=1会变成负数,后续循环中该高位无法提供有效借位,导致while循环持续执行。 - 未处理长度不匹配:如果当前
numbs长度小于被减数的numbs长度,直接访问numbs[i]会存在越界风险,也可能引发逻辑错误。 - 频繁调用fixNum():在循环内部每次减法后调用
fixNum(),频繁修改数组结构,不仅影响性能,还可能干扰后续减法的位运算逻辑。
修复后的sub函数代码
IdleNumb sub(IdleNumb? number) { if (number == null) return this; // 确保当前numbs长度不小于被减数,不足补0 while (numbs.length < number.numbs.length) { numbs.add(0); } for (int i = 0; i < number.numbs.length; i++) { // 当前位不够减时触发借位逻辑 while (numbs[i] < number.numbs[i]) { // 从高位寻找可借位的有效位置 int borrowIndex = i + 1; while (borrowIndex < numbs.length && numbs[borrowIndex] == 0) { borrowIndex++; } // 处理被减数大于当前数的情况(放置游戏可根据需求调整,避免死循环) if (borrowIndex >= numbs.length) { numbs[i] = number.numbs[i] - numbs[i]; for (int j = 0; j <= i; j++) { numbs[j] = -numbs[j]; } break; } // 执行借位:高位减1,当前位补全基数 numbs[borrowIndex] -= 1; numbs[i] += 94868330; // 基数与fixNum的进位阈值一致 // 填充中间位为最大值(避免后续借位异常) for (int j = i + 1; j < borrowIndex; j++) { numbs[j] = 94868329; } } numbs[i] = numbs[i].toInt() - number.numbs[i].toInt(); } // 所有减法完成后统一修正数值 fixNum(); return this; }
更高效的数值方案建议
放置游戏的超大数值运算,不建议用数组分段存储,推荐尾数+指数的科学计数法模式,运算速度更快且无溢出风险:
class IdleNumber { double mantissa; // 范围可设为1.0~1000.0,根据需求调整 int exponent; IdleNumber(this.mantissa, this.exponent); IdleNumber sub(IdleNumber other) { // 对齐指数 if (exponent > other.exponent) { double adjustedOther = other.mantissa * pow(10, other.exponent - exponent); double newMantissa = mantissa - adjustedOther; return _normalize(newMantissa, exponent); } else if (exponent < other.exponent) { double adjustedSelf = mantissa * pow(10, exponent - other.exponent); double newMantissa = adjustedSelf - other.mantissa; return _normalize(newMantissa, other.exponent); } else { double newMantissa = mantissa - other.mantissa; return _normalize(newMantissa, exponent); } } // 标准化尾数和指数 IdleNumber _normalize(double mantissa, int exponent) { while (mantissa < 1.0 && exponent > 0) { mantissa *= 10; exponent--; } while (mantissa >= 1000.0) { mantissa /= 10; exponent++; } return IdleNumber(mantissa, exponent); } }
内容的提问来源于stack exchange,提问作者Tester Lane
相关产品推荐
相关产品推荐

