📄 float.java
字号:
long e1=m_E;
long e2=x.m_E;
long v1=m_Val;
long v2=x.m_Val;
//
if((v1==0 && v2==0) || (v1==v2 && e1==e2))
return true;
// Values with exponent differences more than 20 times never could be equal
/*
if(Math.abs(e1-e2)>20)
return false;
*/
long diff=e1-e2;
if(diff<-20 || diff>20)
return false;
//
while (e1 != e2)
{
if(e1 > e2)
{
if(Math.abs(v1)<maxLimit)
{
v1*=10;
e1--;
}
else
{
v2/=10;
e2++;
}
}
else
if(e1 < e2)
{
if(Math.abs(v2)<maxLimit)
{
v2*=10;
e2--;
}
else
{
v1/=10;
e1++;
}
}
}
//
return (v1==v2);
}
/**
* Reverse sign of value in current Float object and return as new Float object
* @return Float - new Float object
*/
public Float Neg()
{
return new Float(-m_Val, m_E);
}
/**
* Returns the trigonometric sine of an angle. Special cases: If the argument is NaN or an infinity, then the result is NaN. If the argument is zero, then the result is a zero with the same sign as the argument. A result must be within 1 ulp of the correctly rounded result. Results must be semi-monotonic
* @param x Float - an angle, in radians
* @return Float - the sine of the argument
*/
static public Float sin(Float x)
{
while( x.Great(PI) )
x=x.Sub(PImul2);
while( x.Less(PI.Neg()) )
x=x.Add(PImul2);
// x*x*x
Float m1=x.Mul(x.Mul(x));
Float q1=m1.Div(6L);
// x*x*x*x*x
Float m2=x.Mul(x.Mul(m1));
Float q2=m2.Div(120L);
// x*x*x*x*x*x*x
Float m3=x.Mul(x.Mul(m2));
Float q3=m3.Div(5040L);
// x*x*x*x*x*x*x*x*x
Float m4=x.Mul(x.Mul(m3));
Float q4=m4.Div(362880L);
// x*x*x*x*x*x*x*x*x*x*x
Float m5=x.Mul(x.Mul(m4));
Float q5=m5.Div(39916800L);
//
Float result=x.Sub(q1).Add(q2).Sub(q3).Add(q4).Sub(q5);
// 1e-6
if(result.Less(new Float(-999999, -6)))
return new Float(-1L);
// 1e-6
if(result.Great(new Float(999999, -6)))
return new Float(1L);
// 5e-4
if(result.Great(new Float(-5, -4)) && result.Less(new Float(5, -4)))
return new Float(0L);
//
return result;
}
/**
* Returns the trigonometric cosine of an angle. Special cases: If the argument is NaN or an infinity, then the result is NaN. A result must be within 1 ulp of the correctly rounded result. Results must be semi-monotonic
* @param x Float - an angle, in radians
* @return Float - the cosine of the argument
*/
static public Float cos(Float x)
{
while( x.Great(PI) )
x=x.Sub(PImul2);
while( x.Less(PI.Neg()) )
x=x.Add(PImul2);
// x*x
Float m1=x.Mul(x);
Float q1=m1.Div(2L);
// x*x*x*x
Float m2=m1.Mul(m1);
Float q2=m2.Div(24L);
// x*x*x*x*x*x
Float m3=m1.Mul(m2);
Float q3=m3.Div(720L);
// x*x*x*x*x*x*x*x
Float m4=m2.Mul(m2);
Float q4=m4.Div(40320L);
// x*x*x*x*x*x*x*x*x*x
Float m5=m4.Mul(m1);
Float q5=m5.Div(3628800L);
Float result=ONE.Sub(q1).Add(q2).Sub(q3).Add(q4).Sub(q5);
// 1e-6
if(result.Less(new Float(-999999, -6)))
return new Float(-1L);
// 1e-6
if(result.Great(new Float(999999, -6)))
return new Float(1L);
// 5e-4
if(result.Great(new Float(-5, -4)) && result.Less(new Float(5, -4)))
return new Float(0L);
//
return result;
}
/**
* Returns the correctly rounded positive square root of a double value. Special cases: If the argument is NaN or less than zero, then the result is NaN. If the argument is positive infinity, then the result is positive infinity. If the argument is positive zero or negative zero, then the result is the same as the argument. Otherwise, the result is the double value closest to the true mathematical square root of the argument value
* @param x Float - a value
* @return Float - the positive square root of a. If the argument is NaN or less than zero, the result is NaN
*/
static public Float sqrt(Float x)
{
int sp=0;
boolean inv=false;
Float a,b;
//
if(x.Less(ZERO))
return new Float(ERROR);
if(x.Equal(ZERO))
return new Float(ZERO);
if(x.Equal(ONE))
return new Float(ONE);
// argument less than 1 : invert it
if(x.Less(ONE))
{
x=ONE.Div(x);
inv=true;
}
//
long e=x.m_E/2;
// exponent compensation
Float tmp=new Float(x.m_Val, x.m_E-e*2);
// process series of division by 16 until argument is <16
while(tmp.Great(new Float(16L)))
{
sp++;
tmp=tmp.Div(16L);
}
// initial approximation
a=new Float(2L);
// Newtonian algorithm
for(int i=ITNUM; i>0; i--)
{
b=tmp.Div(a);
a=a.Add(b);
a=a.Div(2L);
}
// multiply result by 4 : as much times as divisions by 16 took place
while(sp>0)
{
sp--;
a=a.Mul(4L);
}
// exponent compensation
a.m_E+=e;
// invert result for inverted argument
if(inv)
a=ONE.Div(a);
return a;
}
/**
* Returns the trigonometric tangent of an angle. Special cases: If the argument is NaN or an infinity, then the result is NaN. If the argument is zero, then the result is a zero with the same sign as the argument. A result must be within 1 ulp of the correctly rounded result. Results must be semi-monotonic
* @param x Float - an angle, in radians
* @return Float - the tangent of the argument
*/
static public Float tan(Float x)
{
Float c=cos(x);
if(c.Equal(ZERO)) return new Float(ERROR);
return (sin(x).Div(c));
}
/**
* Returns a new Float object initialized to the value represented by the specified String
* @param str String - the string to be parsed
* @param radix int - basement of number
* @return Float - the Float object represented by the string argument
*/
static public Float parse(String str, int radix)
{
// Abs
boolean neg=false;
if(str.charAt(0)=='-')
{
str=str.substring(1);
neg=true;
}
//
int pos=str.indexOf(".");
long exp=0;
// Find exponent position
int pos2=str.indexOf('E');
if(pos2==-1) pos2=str.indexOf('e');
//
if(pos2!=-1)
{
String tmp=new String(str.substring(pos2+1));
exp=Long.parseLong(tmp);
str=str.substring(0, pos2);
}
//
if(pos!=-1)
{
for(int m=pos+1; m<str.length(); m++)
{
if(Character.isDigit(str.charAt(m)))
exp--;
else
break;
}
str=str.substring(0, pos)+str.substring(pos+1);
while(str.length()>1 && str.charAt(0)=='0' && str.charAt(1)!='.')
str=str.substring(1);
}
//
long result=0L;
int len=str.length();
//
StringBuffer sb=new StringBuffer(str);
while(true)
{
// Long value can't have length more than 20
while(len>20)
{
// Very large number for Long
sb=sb.deleteCharAt(len-1);
// Compensation of removed zeros
if(len<pos || pos==-1)
exp++;
//
len--;
}
//
try
{
result=Long.parseLong(sb.toString(), radix);
if(neg)
result=-result;
break;
}
catch(Exception e)
{
// Very large number for Long
sb=sb.deleteCharAt(len-1);
// Compensation of removed zeros
if(len<pos || pos==-1)
exp++;
//
len--;
}
}
sb=null;
//
Float newValue=new Float(result, exp);
newValue.RemoveZero();
return newValue;
}
/**
* Returns the arc cosine of an angle, in the range of 0.0 through pi. Special case: If the argument is NaN or its absolute value is greater than 1, then the result is NaN. A result must be within 1 ulp of the correctly rounded result. Results must be semi-monotonic
* @param x Float - the value whose arc cosine is to be returned
* @return Float - the arc cosine of the argument
*/
static public Float acos(Float x)
{
Float f=asin(x);
if(f.isError())
return f;
return PIdiv2.Sub(f);
}
/**
* Returns the arc sine of an angle, in the range of -pi/2 through pi/2. Special cases: If the argument is NaN or its absolute value is greater than 1, then the result is NaN. If the argument is zero, then the result is a zero with the same sign as the argument. A result must be within 1 ulp of the correctly rounded result. Results must be semi-monotonic
* @param x Float - the value whose arc sine is to be returned
* @return Float - the arc sine of the argument
*/
static public Float asin(Float x)
{
if( x.Less(ONE.Neg()) || x.Great(ONE) ) return new Float(ERROR);
if( x.Equal(ONE.Neg()) ) return PIdiv2.Neg();
if( x.Equal(ONE) ) return PIdiv2;
return atan(x.Div(sqrt(ONE.Sub(x.Mul(x)))));
}
/**
* Returns the arc tangent of an angle, in the range of -pi/2 through pi/2. Special cases: If the argument is NaN, then the result is NaN. If the argument is zero, then the result is a zero with the same sign as the argument. A result must be within 1 ulp of the correctly rounded result. Results must be semi-monotonic
* @param x Float - the value whose arc tangent is to be returned
* @return Float - the arc tangent of the argument
*/
static public Float atan(Float x)
{
boolean signChange=false;
boolean Invert=false;
int sp=0;
Float x2, a;
// check up the sign change
if(x.Less(ZERO))
{
x=x.Neg();
signChange=true;
}
// check up the invertation
if(x.Great(ONE))
{
x=ONE.Div(x);
Invert=true;
}
// process shrinking the domain until x<PI/12
while(x.Great(PIdiv12))
{
sp++;
a=x.Add(SQRT3);
a=ONE.Div(a);
x=x.Mul(SQRT3);
x=x.Sub(ONE);
x=x.Mul(a);
}
// calculation core
x2=x.Mul(x);
a=x2.Add(new Float(14087812, -7));
a=new Float(55913709, -8).Div(a);
a=a.Add(new Float(60310579, -8));
a=a.Sub(x2.Mul(new Float(5160454, -8)));
a=a.Mul(x);
// process until sp=0
while(sp>0)
{
a=a.Add(PIdiv6);
sp--;
}
// invertation took place
if(Invert) a=PIdiv2.Sub(a);
// sign change took place
if(signChange) a=a.Neg();
//
return a;
}
/**
* Converts rectangular coordinates (x,爕) to polar (r,爐heta). This method computes the phase theta by computing an arc tangent of y/x in the range of -pi to pi. Special cases: If either argument is NaN, then the result is NaN. If the first argument is positive zero and the second argument is positive, or the first argument is positive and finite and the second argument is positive infinity, then the result is positive zero. If the first argument is negative zero and the second argument is positive, or the first argument is negative and finite and the second argument is positive infinity, then the result is negative zero. If the first argument is positive zero and the second argument is negative, or the first argument is positive and finite and the second argument is negative infinity, then the result is the double value closest to pi. If the first argument is negative zero and the second argument is negative, or the first argument is negative and finite and the second argument is negative infinity, then the result is the double value closest to -pi. If the first argument is positive and the second argument is positive zero or negative zero, or the first argument is positive infinity and the second argument is finite, then the result is the double value closest to pi/2. If the first argument is negative and the second argument is positive zero or negative zero, or the first argument is negative infinity and the second argument is finite, then the result is the double value closest to -pi/2. If both arguments are positive infinity, then the result is the double value closest to pi/4. If the first argument is positive infinity and the second argument is negative infinity, then the result is the double value closest to 3*pi/4. If the first argument is negative infinity and the second argument is positive infinity, then the result is the double value closest to -pi/4. If both arguments are negative infinity, then the result is the double value closest to -3*pi/4. A result must be within 2 ulps of the correctly rounded result. Results must be semi-monotonic
* @param y Float - the ordinate coordinate
* @param x Float - the abscissa coordinate
* @return Float - the theta component of the point (r,爐heta) in polar coordinates that corresponds to the point (x,爕) in Cartesian coordinates
*/
static public Float atan2(Float y, Float x)
{
// if x=y=0
if(y.Equal(ZERO) && x.Equal(ZERO))
return new Float(ZERO);
// if x>0 atan(y/x)
if(x.Great(ZERO))
return atan(y.Div(x));
// if x<0 sign(y)*(pi - atan(|y/x|))
if(x.Less(ZERO))
{
if(y.Less(ZERO))
return Float.PI.Sub(atan(y.Div(x))).Neg();
else
return Float.PI.Sub(atan(y.Div(x).Neg()));
}
// if x=0 y!=0 sign(y)*pi/2
if(y.Less(ZERO))
return PIdiv2.Neg();
else
return new Float(PIdiv2);
}
// precise
// x=-35 diff=1.48%
// x=-30 diff=0.09%
// x=30 diff=0.09%
// x=31 diff=0.17%
// x=32 diff=0.31%
// x=33 diff=0.54%
// x=34 diff=0.91%
// x=35 diff=1.46%
/**
* Returns Euler's number e raised to the power of a double value. Special cases: If the argument is NaN, the result is NaN. If the argument is positive infinity, then the result is positive infinity. If the argument is negative infinity, then the result is positive zero. A result must be within 1 ulp of the correctly rounded result. Results must be semi-monotonic
* @param x Float - the exponent to raise e to
* @return Float - the value e^x, where e is the base of the natural logarithms
*/
static public Float exp(Float x)
{
if(x.Equal(ZERO))
return new Float(ONE);
//
Float f=new Float(ONE);
long d=1;
Float k=null;
boolean isless=x.Less(ZERO);
if(isless)
x=x.Neg();
k=new Float(x).Div(d);
//
for(long i=2; i<50; i++)
{
f=f.Add(k);
k=k.Mul(x).Div(i);
}
//
if(isless)
return ONE.Div(f);
else
return f;
}
// precise
// x=25 diff=0.12%
// x=30 diff=0.25%
// x=35 diff=0.44%
// x=40 diff=0.67%
/**
* Internal log subroutine
* @param x Float
* @return Float
*/
static private Float _log(Float x)
{
if(!x.Great(ZERO))
return new Float(ERROR);
//
Float f=new Float(ZERO);
// Make x to close at 1
int appendix=0;
while(x.Great(ZERO) && x.Less(ONE))
{
x=x.Mul(2);
appendix++;
}
//
x=x.Div(2);
appendix--;
//
Float y1=x.Sub(ONE);
Float y2=x.Add(ONE);
Float y=y1.Div(y2);
//
Float k=new Float(y);
y2=k.Mul(y);
//
for(long i=1; i<50; i+=2)
{
f=f.Add(k.Div(i));
k=k.Mul(y2);
}
//
f=f.Mul(2);
for(int i=0; i<appendix; i++)
f=f.Add(LOGdiv2);
//
return f;
}
/**
* Returns the natural logarithm (base e) of a double value. Special cases: If the argument is NaN or less than zero, then the result is NaN. If the argument is positive infinity, then the result is positive infinity. If the argument is positive zero or negative zero, then the result is negative infinity. A result must be within 1 ulp of the correctly rounded result. Results must be semi-monotonic
* @param x Float - a number greater than 0.0
* @return Float - the value ln(x), the natural logarithm of x
*/
static public Float log(Float x)
{
if(!x.Great(ZERO))
return new Float(ERROR);
//
if(x.Equal(ONE))
return new Float(ZERO);
//
if(x.Great(Float.ONE))
{
x=ONE.Div(x);
return _log(x).Neg();
}
return _log(x);
}
static public Float log10(Float x)
{
if(!x.Great(ZERO))
return new Float(ERROR);
//
if(x.Equal(ONE))
return new Float(ZERO);
//
Float f=log(x);
if(f.isError())
return f;
return f.Div(LOG10);
}
/*
static public Float log10(Float x)
{
if(!x.Great(ZERO))
return new Float(ERROR);
//
boolean neg=false;
if(x.m_Val<0)
{
neg=true;
x.m_Val=-x.m_Val;
}
//
int index=0;
if(x.Great(Float.ONE))
{
// 令朦
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -