在编写JavaScript策略时,由于脚本语言自身的一些问题,经常导致计算时数值精确度问题。对于程序中一些计算、逻辑判断有一定影响。例如,在计算1 - 0.8
或者0.33 * 1.1
时,会计算出有误差的数据:
function main() {
var a = 1 - 0.8
Log(a)
var c = 0.33 * 1.1
Log(c)
}
那么如何解决此类问题呢?问题根源在于:
浮点数值的最高进度是17位小数,但在进行运算的时候其精确度却远远不如整数;整数在进行运算的时候都会转成10进制; 而Java和JavaScript中计算小数运算时,都会先将十进制的小数换算到对应的二进制,一部分小数并不能完整的换算为二进制,这里就出现了第一次的误差。待小数都换算为二进制后,再进行二进制间的运算,得到二进制结果。然后再将二进制结果换算为十进制,这里通常会出现第二次的误差。
为了解决这个问题,在网上搜索了一些解决方案,经过测试使用,如下方案比较好的解决了这个问题:
function mathService() {
// 加法
this.add = function(a, b) {
var c, d, e;
try {
c = a.toString().split(".")[1].length; // 获取a的小数位长度
} catch (f) {
c = 0;
}
try {
d = b.toString().split(".")[1].length; // 获取b的小数位长度
} catch (f) {
d = 0;
}
//先求e,把a、b 同时乘以e转换成整数相加,再除以e还原
return e = Math.pow(10, Math.max(c, d)), (this.mul(a, e) + this.mul(b, e)) / e;
}
// 乘法
this.mul = function(a, b) {
var c = 0,
d = a.toString(), // 转换为字符串
e = b.toString(); // ...
try {
c += d.split(".")[1].length; // c 累加a的小数位长度
} catch (f) {}
try {
c += e.split(".")[1].length; // c 累加b的小数位长度
} catch (f) {}
// 转换为整数相乘,再除以10^c ,移动小数点,还原,利用整数相乘不会丢失精度
return Number(d.replace(".", "")) * Number(e.replace(".", "")) / Math.pow(10, c);
}
// 减法
this.sub = function(a, b) {
var c, d, e;
try {
c = a.toString().split(".")[1].length; // 获取a的小数位长度
} catch (f) {
c = 0;
}
try {
d = b.toString().split(".")[1].length; // 获取b的小数位长度
} catch (f) {
d = 0;
}
// 和加法同理
return e = Math.pow(10, Math.max(c, d)), (this.mul(a, e) - this.mul(b, e)) / e;
}
// 除法
this.div = function(a, b) {
var c, d, e = 0,
f = 0;
try {
e = a.toString().split(".")[1].length;
} catch (g) {}
try {
f = b.toString().split(".")[1].length;
} catch (g) {}
// 同理,转换为整数,运算后,还原
return c = Number(a.toString().replace(".", "")), d = Number(b.toString().replace(".", "")), this.mul(c / d, Math.pow(10, f - e));
}
}
function main() {
var obj = new mathService()
var a = 1 - 0.8
Log(a)
var b = obj.sub(1, 0.8)
Log(b)
var c = 0.33 * 1.1
Log(c)
var d = obj.mul(0.33, 1.1)
Log(d)
}
究其原理,是把要做运算的两个操作数转换为整数去计算避免精度问题,在计算后(根据转换为整数时的放大倍数)对计算结果运算还原,得出准确结果。
这样当我们想让程序在盘口价格加一跳最小价格精度的时候挂单,就不用担心数值精度问题了
function mathService() {
.... // 省略
}
function main() {
var obj = new mathService()
var depth = exchange.GetDepth()
exchange.Sell(obj.add(depth.Bids[0].Price, 0.0001), depth.Bids[0].Amount, "买一订单:", depth.Bids[0])
}
有兴趣的同学,可以读一下代码,了解计算过程,欢迎提出问题,一起学习一起进步。
深圳SEO优化公司专业的优化网站哪家便宜电影网站如何做seo优化网站搜索优化哪家专业册亨县网站优化服务封开新站网站优化图片类网站如何优化网站按天计费优化推广优化网站就选h火10星评价什么是网站外部优化推广优化网站收录seo网站优化视频官渡网站优化推广南京网站seo优化软件企业如何进行网站优化网站seo优化关键词技巧上海优化网站公司哪家好杭州网站优化排名衢州百度网站按天优化太原网站优化在线咨询推广网站优化的费用马鞍山专业网站优化郑州网站seo优化软件福田广告网站优化如何做温州网站关键词百度优化优化公司网站灵巧云速捷推荐优化公司网站关键词明光正规的网站优化成都网络优化网站济南正宗网站优化费用福建网站seo优化培训歼20紧急升空逼退外机英媒称团队夜以继日筹划王妃复出草木蔓发 春山在望成都发生巨响 当地回应60岁老人炒菠菜未焯水致肾病恶化男子涉嫌走私被判11年却一天牢没坐劳斯莱斯右转逼停直行车网传落水者说“没让你救”系谣言广东通报13岁男孩性侵女童不予立案贵州小伙回应在美国卖三蹦子火了淀粉肠小王子日销售额涨超10倍有个姐真把千机伞做出来了近3万元金手镯仅含足金十克呼北高速交通事故已致14人死亡杨洋拄拐现身医院国产伟哥去年销售近13亿男子给前妻转账 现任妻子起诉要回新基金只募集到26元还是员工自购男孩疑遭霸凌 家长讨说法被踢出群充个话费竟沦为间接洗钱工具新的一天从800个哈欠开始单亲妈妈陷入热恋 14岁儿子报警#春分立蛋大挑战#中国投资客涌入日本东京买房两大学生合买彩票中奖一人不认账新加坡主帅:唯一目标击败中国队月嫂回应掌掴婴儿是在赶虫子19岁小伙救下5人后溺亡 多方发声清明节放假3天调休1天张家界的山上“长”满了韩国人?开封王婆为何火了主播靠辱骂母亲走红被批捕封号代拍被何赛飞拿着魔杖追着打阿根廷将发行1万与2万面值的纸币库克现身上海为江西彩礼“减负”的“试婚人”因自嘲式简历走红的教授更新简介殡仪馆花卉高于市场价3倍还重复用网友称在豆瓣酱里吃出老鼠头315晚会后胖东来又人满为患了网友建议重庆地铁不准乘客携带菜筐特朗普谈“凯特王妃P图照”罗斯否认插足凯特王妃婚姻青海通报栏杆断裂小学生跌落住进ICU恒大被罚41.75亿到底怎么缴湖南一县政协主席疑涉刑案被控制茶百道就改标签日期致歉王树国3次鞠躬告别西交大师生张立群任西安交通大学校长杨倩无缘巴黎奥运