📄 float.java
字号:
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
*/
private static 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 = 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
*/
private static 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
*/
private static 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,�y) to polar (r,�theta). 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,�theta) in polar
* coordinates that corresponds to the point (x,�y) 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
*/
private static 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -