本文共 7673 字,大约阅读时间需要 25 分钟。
晚上加班的时候,策划一直在耳边念叨数值的事儿。有些心烦意乱,顺口吐槽到,不如把数值运算丢给服务器人员去算。
哪知策划立马就说,这不行,他们原来服务器进行六十多位的运算时候,服务器炸了。
一说这个我就不乐意了,正好前端时间写了个超大数运算的方法,拿来检测下。
var _nu = "83497893246298346827346872346982360823579357623984623957438574309580293583209572309857846982364932784687236478921740172340912784901274879216478916298461298437612984316712984761298471298471284798124791284782146871324617892461928746981723647438926478321740912374809128740128409217844321462141912849021834274623784631728461782461728"; var _f = "543897489324789234723884709284201480924788903275498327"; Debug.Log(LargeNumberCalculator.BigDatenumMulitfy(_nu, _f));
运算结果如图所示:
45414294500570946232766941981487532736101951529219837603814751565682140750606060305830153788739377945894441114448047125337713342779005019904853971980122004902613506487483958423414305100219402340260863310057396394835279845410829944230707927439104713224781013599416389511098350559798301920310589352886075269035259304696264356729808295144044599752214530030747527087148415956028005529056
大致验算下,位数7*8=56是正确的。具体的数换个计算方式一样,说明应该是正确的。
再换个数计算:
var _nu = "83497893246298346827346872346982360823579357623984623957438574309580293583209572309857846982364932784687236478921740172340912784901274879216478916298461298437612984316712984761298471298471284798124791284782146871324617892461928746981723647438926478321740912374809128740128409217844321462141912849021834274623784631728461782461728"; var _f = "7000000000000000000"; Debug.Log(LargeNumberCalculator.BigDatenumMulitfy(_nu, _f));
结果为:
584485252724088427791428106428876525765055503367892367702070020167062055082467006169004928876554529492810655352452181206386389494308924154515352414089229089063290890216990893329089299089298993586873538993475028099272325247233501228872065532072485348252186386623663901180898864524910250234993389943152839922366492422099232477232096000000000000000000
首位运算大致没错,耗时不到几毫秒,起码不会蹦。
这个梗可真是:我曾在极度愤怒的情况下,完成几百位的乘法运算。
代码用的是之前写的天文级别运算方法,按位去计算。不过其实C#是提供有个BigInteger类来处理的。这里公开下关于BigInteger部分的源码:
using System.Collections;using System.Collections.Generic;using System.Numerics;using UnityEngine;////// 大数计算器/// public class LargeNumberCalculator{ ////// 大数比较 /// public static bool BigDateCompare(string _st1, string _st2) { var _sA1 = _st1.Split('.'); var _sA2 = _st2.Split('.'); try { BigInteger _b1 = BigInteger.Parse(_sA1[0]); BigInteger _b2 = BigInteger.Parse(_sA2[0]); if (BigInteger.Compare(_b1, _b2) >= 0) return true; } catch { } return false; } ////// 大数相加 /// public static string BigDataPlus(string _st1, string _st2) { var _sA1 = _st1.Split('.'); var _sA2 = _st2.Split('.'); try { BigInteger _b1 = BigInteger.Parse(_sA1[0]); BigInteger _b2 = BigInteger.Parse(_sA2[0]); _b1 = BigInteger.Add(_b1, _b2); var _num = 0f; if (_sA1.Length > 1) _num += GetBigdateFloat(_sA1[1]); if (_sA2.Length > 1) _num += GetBigdateFloat(_sA2[1]); _b1 = BigInteger.Add(_b1, (int)_num); return GetFewBehind("" + _b1,_num); } catch { } return _st1; } ////// 大数相减:只支持被减数大于减数 /// public static string BigDataSUB(string _st1, string _st2) { var _sA1 = _st1.Split('.'); var _sA2 = _st2.Split('.'); try { BigInteger _b1 = BigInteger.Parse(_sA1[0]); BigInteger _b2 = BigInteger.Parse(_sA2[0]); if (BigInteger.Compare(_b1, _b2) < 0) return "0"; _b1 = BigInteger.Subtract(_b1, _b2); var _num = 0f; if (_sA1.Length > 1) _num += GetBigdateFloat(_sA1[1]); if (_sA2.Length > 1) { //借一位相减 _b1 = BigInteger.Add(_b1, -1); _num = _num + 1 - GetBigdateFloat(_sA2[1]); } _b1 = BigInteger.Add(_b1, (int)_num); return GetFewBehind("" + _b1, _num); } catch { } return _st1; } ////// 计算某位与一个数字相乘 /// public static string BigDatenumMulitfy(string _s1, string _s2) { //Debug.Log("~~~~~~~~~~~~~"+_s1+" "+_s2); var _sA1 = _s1.Split('.'); var _sA2 = _s2.Split('.'); try { var _num = 1; var _get1 = "" + _sA1[0]; var _get2 = "" + _sA2[0]; if (_sA1.Length > 1) { _get1 += "" + GetBigdateIntToString(_sA1[1]); //Debug.Log(_get1); _num *= 1000; } if (_sA2.Length > 1) { _get2 += "" + GetBigdateIntToString(_sA2[1]); //Debug.Log(_get2); _num *= 1000; } BigInteger _b1 = BigInteger.Parse(_get1); BigInteger _b2 = BigInteger.Parse(_get2); //Debug.Log(_b1 + " " + _b2); _b1 = BigInteger.Multiply(_b1, _b2); //Debug.Log(_b1 + " " + _num); BigInteger _remainder = 0; _b1 = BigInteger.DivRem(_b1, _num, out _remainder); //Debug.Log("..." + _b1); //Debug.Log(BigDateRounding(GetStrForBigdate("" + _remainder, _num)) + " " + GetStrForBigdate("" + _remainder, _num)); if (_remainder > 0) return _b1 + "." + BigDateRounding(GetStrForBigdate("" + _remainder, _num)); return ""+_b1; } catch { } return _s1; } ////// 大数与float相乘,得出一个大数 /// public static string BigDatenumMulitfy(string _str1, float _f2) { return BigDatenumMulitfy(_str1, _f2.ToString()); } ////// float与float相乘,得出一个大数 /// public static string BigDatenumMulitfy(float _f1, float _f2) { return BigDatenumMulitfy(_f1.ToString(), _f2); } ////// 获得只包含前三位的float值 /// private static float GetBigdateFloat(string _str) { var _arr = _str.ToCharArray(); var _zero = "0."; for (var _i = 0; _i < 3; _i++) { if (_i < _arr.Length) _zero += _arr[_i]; } return float.Parse(_zero); } private static string GetBigdateIntToString(string _str) { var _arr = _str.ToCharArray(); var _zero = ""; for (var _i = 0; _i < 3; _i++) { if (_i < _arr.Length) _zero += _arr[_i]; else _zero += "0"; } return /*int.Parse*/(_zero); } private static string GetStrForBigdate(string _str,int _bit) { _bit = _bit.ToString().Length - 1; var _cNum = _bit - _str.Length; for (var _i = 0; _i < _cNum; _i++) _str = "0" + _str; _str = _str.Substring(0, 3); return BigDateRounding(_str); } ////// 后去零 /// private static string BigDateRounding(string _str) { for (var _i = _str.Length - 1; _i >= 0; _i--) { if (_str[_i] == '0') { _str = _str.Substring(0, _str.Length - 1); } else return _str; } return _str; } ////// 补全小数点后几位 /// ///private static string GetFewBehind(string _str, float _f) { var _arr = _f.ToString().Split('.'); if (_arr.Length > 1) { _str += "."; var _theArr = _arr[1].ToCharArray(); for (var _i = 0; _i < 3; _i++) { if (_i < _theArr.Length) _str += _theArr[_i]; } return _str; } else { return _str; } }}
这个思路也是拼接运算,其实放到java或者其他语言里面去,计算原理也是一样。
有需要的朋友,自己拿去。
转载地址:http://iowli.baihongyu.com/