<<上篇 | 首页 | 下篇>>

javascript中的不损失精度数学计算函数

//除法函数,用来得到精确的除法结果
//说明:javascript的除法结果会有误差,在两个浮点数相除的时候会比较明显。这个函数返回较为精确的除法结果。
//调用:accDiv(arg1,arg2)
//返回值:arg1除以arg2的精确结果

function accDiv(arg1,arg2){
var t1=0,t2=0,r1,r2;
try{t1=arg1.toString().split(".")[1].length}catch(e){}
try{t2=arg2.toString().split(".")[1].length}catch(e){}
with(Math){
r1=Number(arg1.toString().replace(".",""))
r2=Number(arg2.toString().replace(".",""))
return (r1/r2)*pow(10,t2-t1);
}
}
//给Number类型增加一个div方法,调用起来更加方便。
Number.prototype.div = function (arg){
return accDiv(this, arg);
}
//乘法函数,用来得到精确的乘法结果
//说明:javascript的乘法结果会有误差,在两个浮点数相乘的时候会比较明显。这个函数返回较为精确的乘法结果。
//调用:accMul(arg1,arg2)
//返回值:arg1乘以arg2的精确结果
function accMul(arg1,arg2)
{
var m=0,s1=arg1.toString(),s2=arg2.toString();
try{m+=s1.split(".")[1].length}catch(e){}
try{m+=s2.split(".")[1].length}catch(e){}
return Number(s1.replace(".",""))*Number(s2.replace(".",""))/Math.pow(10,m)
}
//给Number类型增加一个mul方法,调用起来更加方便。
Number.prototype.mul = function (arg){
return accMul(arg, this);
}
//加法函数,用来得到精确的加法结果
//说明:javascript的加法结果会有误差,在两个浮点数相加的时候会比较明显。这个函数返回较为精确的加法结果。
//调用:accAdd(arg1,arg2)
//返回值:arg1加上arg2的精确结果
function accAdd(arg1,arg2){
var r1,r2,m;
try{r1=arg1.toString().split(".")[1].length}catch(e){r1=0}
try{r2=arg2.toString().split(".")[1].length}catch(e){r2=0}
m=Math.pow(10,Math.max(r1,r2))
return (arg1*m+arg2*m)/m
}
//给Number类型增加一个add方法,调用起来更加方便。
Number.prototype.add = function (arg){
return accAdd(arg,this);
}


function Subtr(arg1,arg2){
     var r1,r2,m,n;
     try{r1=arg1.toString().split(".")[1].length}catch(e){r1=0}
     try{r2=arg2.toString().split(".")[1].length}catch(e){r2=0}
     m=Math.pow(10,Math.max(r1,r2));
     //last modify by deeka
     //动态控制精度长度
     n=(r1>=r2)?r1:r2;
     return ((arg1*m-arg2*m)/m).toFixed(n);
}

标签 : ,

java中的高精度数学计算函数

Math类:
  java.lang.Math类中包含基本的数字操作,如指数、对数、平方根和三角函数。
  java.math是一个包,提供用于执行任意精度整数(BigInteger)算法和任意精度小数(BigDecimal)算法的类。
 
  java.lang.Math类中包含E和PI两个静态常量,以及进行科学计算的类(static)方法,可以直接通过类名调用。
  public static final Double E = 2.7182818284590452354 
  public static final Double PI = 3.14159265358979323846
 
  public static long abs(double x):传回 x 的绝对值。X也可int long float
  public static long sin(double x): 传回x径度的正弦函数值  
  public static long cos(double x):传回x径度的余弦函数值   
  public static long tan(double x): 传回x径度的正切函数值 
  public static long asin(double x):传回x值的反正弦函数值。
  public static long acos(double x):传回x值的反余弦函数值。
  public static long atan(double x):传回x值的反正切函数值。 
  public static long atan2(double x, double y):传回极坐标(polar)的θ值 
  public static long floor(double x):传回不大于x的最大整数值 
  public static long ceil(double x):传回不小于x的最小整数值。 
  public static long exp(double x):传回相当于ex值 
  public static long log(double x):传回x的自然对数函数值 
  public static long max(double x,double y):传回x、y较大数 
  public static long min(double x,double y):传回x、y较小数 
  public static long pow(double x,double y):传回x的y次幂值 
  public static long sqrt(double x): 传回x开平方值 
  public static long rint(double x):传回最接近x的整数值 
  public static long round(double x):传回x的四舍五入值 
  public static long toDegrees(double angrad):传回将angrad径度转换成角度 
  public static long toRadians(double angdeg): 传回将angdeg角度转换成径度
  public static long random():传回随机数值,产生一个0-1之间的随机数(不包括0和1)
 
NumberFormat类:
 
(public abstract class NumberFormat extends Format)
用java.text.NumberFormat类对输出的数字结果进行必要的格式化。

  使用该类如下方法类实例化一个NumberFormat对象:
   public static final NumberFormat getInstance()
  然后用该对象调用如下方法可以格式化数字number(返回字符串对象):
   public final String format(double number)
 
  NumberFormat类有如下常用方法:
  public void setMaximumFractionDigits(int newValue)//设置数的小数部分所允许的最大位数。
  public void setMaximumIntegerDigits(int newValue)//设置数的整数部分所允许的最大位数。
  public void setMinimumFractionDigits(int newValue)//设置数的小数部分所允许的最小位数。
  public void setMinimumIntegerDigits(int newValue)//设置数的整数部分所允许的最小位数。
  (更多方法及用法看JDK6API参考。)
 

 BigInteger类、BigDecimal类:
  java.math包中的BigInteger类和BigDecimal类分别提供任意精度的整数和小数运算。
  两个类设计思想一样,这里只对BigInterger类稍做介绍,细节可以查看JDK6API参考。
 
  构造方法如下:
   BigInteger(String val)  //将 BigInteger 的十进制字符串表示形式转换为 BigInteger。
   还有很多考虑周全的构造函数,建议要准备写特殊需求的BigInteger前先认真翻下JDK。
 
  常用方法:
   abs()  //返回其值是此BigInteger的绝对值的BigInteger。
   add(BigInteger val)  //返回其值为(this+val)的BigInteger。
   subtract(BigInteger val)  //返回其值为(this-val)的BigInteger。
   multiply(BigInteger val)  // 返回其值为(this*val)的BigInteger。
   divide(BigInteger val)  //返回其值为(this/val)的BigInteger。
   remainder(BigInteger val)  //返回其值为(this%val)的BigInteger。
   compareTo(BigInteger val)  //将此BigInteger与指定的BigInteger进行比较。返回值1、0、-1分别表示大于、等于、小于
   pow(int exponent)  //返回当前大数的exponent次幂。
   toString()  //返回此BigInteger的十进制字符串表示形式。
   toString(int radix)  //返回此BigInteger的给定基数(radix进制)的字符串表示形式。

补充:

(1)abs():返回某数字的绝对值.参数可以是float、double、long或int。如果是byte或short类型,那么它们会被强制转换成int类型。
(2)ceil()会找到下一个最大整数。例如参数为9.01时,返回10.0。为-0.1时,返回-0.0。返回比参数大的整数,而且都是双精度类型的。如果参数是整数,则该方法会返回这个参数的双精度型。
(3)floor()返回紧邻的最小整数。作用与ceil()正好相反,返回的是比参数小的整数,而且都是双精度型。如果参数为整数,则返回这个参数的双精度型。
(4)max()返回两个值中的最大值,只支持float double long int 不支持byte short。
(5)min()返回两个值中的最小值,只支持float double long int 不支持byte short。
(6)random()返回一个随机数,一个在0.0到1.0之间的双精度数。
(7)round()返回与某浮点数值最接近的整数值。参数可以为double和folat两种,而且支持四舍五入。例如:参数为9.01时,返回9,参数为9.5时,返回10,参数为-9.5时,返回-9。
(8)sqrt()返回某数值的平方根。如果该参数是"非数字"类型(NaN),或者小于零,则返回是NaN。

 

标签 : ,

为什么敏捷方法能够在软件开发领域行之有效?

文章来源 – Martin Fowler 和 Neal Ford 在 Paris – USI 2010 的演讲

有很多的书籍讨论敏捷方法是怎样工作的(How it works?),在这个主题演讲中,Martin Fowler 和他的同事 Neal Ford 讨论了敏捷方法能够在软件开发项目中行之有效的原因(Why it works?)。作为敏捷方法的发起人和传道者,Martin Fowler 和 ThoughtWorks 一直试图从理论层面证明敏捷方法的可行性,同时不厌其烦地解答着客户们的各种困惑,正如他们所说,敏捷方法中的很多概念不是特别的直观,除非人们真正实践过一段时间,否则有些概念很难从字面上去完全理解。

Martin Fowler 谈到一个有意思的现象,那就是今天许多人们口中谈论的敏捷方法,和最初的敏捷方法大相径庭,他把这种现象称为“语义扩散(Semantic Diffusion)”,大意是某种思想在传播的过程中,在逐渐扩散的同时,其语义也渐渐变得模糊。在敏捷开发领域里,“语义扩散”导致的一个问题是,在一些使用敏捷方法的项目或者公司中,我们甚至无法辨别出敏捷方法的影子,原因是很多人没有真正地理解敏捷方法,也就不能够正确地运用和实践,从而也就无法真正了解自己是否能够从敏捷方法中获益。

以下是为什么敏捷方法行之有效的原因:

1. 敏捷方法和传统的计划驱动方法的两个主要区别

i. 预测性计划(Predictive Planning)和自适应计划(Adaptive Planning)

计划驱动方法首先计划要做的工作(plan your work),然后着手工作以完成计划(work your plan)。这是一种带有预测性质的方法,其衡量项目成功的标准则是我们是否按计划、按时、按预算完成了工作。这种方法在很多领域里是适用的。但是对于软件开发而言,如果我们的需求没有办法做到不变更的话,我们就无法保证我们的计划以及其后的工作是不会变更的。Martin Fowler 向现场观众提出了一个问题,大意是你们当中有多少人的软件开发项目的需求是一成不变的,结果没有一位观众举手。因此,敏捷方法引入了自适应计划的概念,既然我们无法保证需求不变更,那么就让我们随时准备接受变更,接受挑战吧。自适应计划将计划驱动的流程缩短为以数周为单位的循环周期,在每一个周期中,我们根据当前的情况不断地调整计划以及计划的执行过程,同时不断地产生能够工作的代码,并且不断地将代码部署到应用环境中去。当然要实现这个目标我们需要一些具体方法的支持,如:自测试代码(Self-Testing Code),持续集成(Continuous Integration),重构(Refactoring),和简洁设计(Simple Design)等等这些技术层面上的方法。Martin Fowler 指出,一些公司和项目之所以受困于敏捷方法,原因之一是他们忽略了这些技术层面的方法,而仅仅实施了项目管理层面的方法。

ii. 以流程为本(Process First)和以人为本(People First)

在传统的方法论中,我们总是需要事先定义好工作的方法和流程,然后“工人们”被要求遵照这些方法和流程来工作。在软件开发领域,很多人把软件开发过程等同于软件本身,也就是说,软件开发的过程也如同软件程序般象机器一样运行,组件之间环环相扣,严密地协同工作。问题是软件开发的核心是人,人相对于机器零件和流水线而言,是相对不可预测的和不那么精密的。所以敏捷方法反其道而行之,提倡将“首先定义流程,然后要求软件开发人员遵照流程工作”变为“让参与软件开发的人员自己来定义和选择适合他们的流程”。简单来说就是以人为本,不把人当螺丝钉,发挥人的主观能动性,当然前提是需要团队成员有较高的平均素质。

2. 沟通(Communication)

Neal Ford 让我们回顾或想象一下失败的软件开发项目,它们的失败是由于技术因素还是人的因素呢?《人件》的作者认为都是人的因素。人类的社会性决定了沟通的重要。Neal 举了几个有趣的例子,如:监狱里的犯人宁愿和其他人渣待在一起也不愿被关禁闭。很多国家禁止驾驶员驾驶时打移动电话,那为什么和乘客聊天就没有问题呢?原因是直接对话是最为有效和便捷的沟通方式,信息的传递在对话过程中非常顺畅和完整。虽然现在的移动通讯已经非常先进,信号质量也很高,但是我们的通话过程仍然是有损的,我们的大脑这个时候就需要努力地试图将通话信息拼凑得更完整以便能够理解对方的意思,因此才会分散驾驶的注意力。随后,Martin Fowler 举了另一个例子,拿他做水果蛋糕的方法和他在酒店的浴室中冲凉的方法来进行比较。因为做水果蛋糕的整个流程和配料都是非常固定的,所以他只需要按步照搬地烹饪即可做出味道非常一致(地好或者差)的水果蛋糕。而在酒店中冲凉就有些不同,因为每一个酒店浴室的开关设计几乎都是不一样的,所以他需要不断地调整开关来获得一个理想的水温,也就是需要不断地重复“调整开关”(输入),“用手试温”(输出)这个过程。相对于做水果蛋糕,在酒店浴室冲凉更好地反应了软件开发的特征,这就是在软件开发领域中,如果我们善于根据用户反馈的信息来做出新的判断和调整,就有可能提高产品的质量和用户的满意度。

沟通的确是一个非常重要的环节,它是敏捷方法的核心。在敏捷方法中,单元测试是程序员和代码组件的沟通,功能测试是程序员以及QA和系统的沟通,故事墙(Story Wall)和回顾(Retrospective)是团队和成员之间的沟通,功能演示(Showcase 或者 Demo)是团队通过产品和最终用户的沟通,持续集成(Continuous Integration)是产品和企业计算环境的沟通。沟通好了,什么事情都可以妥善解决,沟通得不好,好事也会变坏事。和广大技术爱好者交流沟通也是酷壳存在的目的和意义。

整个演讲时长一个小时,本文只是节选了我认为比较有意思的观点加上本人的理解写成,如有错误之处欢迎指正,不同看法欢迎交流。

 

标签 :