划分BigIntegers以返回双精度值
我想计算一条直线的斜率。划分BigIntegers以返回双精度值
public sealed class Point
{
public System.Numerics.BigInteger x = 0;
public System.Numerics.BigInteger y = 0;
public double CalculateSlope (Point point)
{
return ((point.Y - this.Y)/(point.X - this.X));
}
}
我知道的BigInteger返回除法结果加上其余但我不知道如何使用它获得双重一个DivRem功能。我正在处理的数字是远远超出Int64.MaxValue的范围,所以其余的本身可能超出范围来计算传统的划分。
编辑: 不知道它是否有帮助,但我只处理正整数(> = 1)。
重要事项:我只需要几个小数点的精度(5应该足够我的目的)。
BigRational库的转换运算符翻倍。此外,请记住将无穷大作为垂直线的特例返回,您将得到一个除以零的异常与您当前的代码。可能最好先计算X1 - X2,如果它为零则返回无穷大,然后进行除法,以避免冗余操作。
有趣。 .NET 4中不存在这个类吗?如果它是测试版或候选版本,那么不幸的是我不能在生产代码中使用它。 – 2012-08-08 20:50:10
这是一个测试版。你为什么不能使用它? – Random832 2012-08-08 22:28:07
这是一个生产应用程序。质量保证不允许测试版库。 – 2012-08-09 01:05:03
这不处理负面,但希望给你一个开始。
double doubleMax = double.MaxValue;
BigInteger numerator = 120;
BigInteger denominator = 50;
if (denominator != 0)
{
Debug.WriteLine(numerator/denominator);
Debug.WriteLine(numerator % denominator);
BigInteger ansI = numerator/denominator;
if (ansI < (int)doubleMax)
{
double slope = (double)ansI + ((double)(numerator % denominator)/(double)denominator); ;
Debug.WriteLine(slope);
}
}
谢谢。但是,如果整体结果在Int32或UInt64内,这只会起作用。考虑将N除以3,其中N具有10,000,000个数字。 – 2012-08-08 20:35:29
@RaheelKhan没错。阅读问题public double CalculateSlope。如果它大于两倍,答案不能被翻倍。 – Paparazzi 2012-08-08 20:41:19
当然。斜率本身总是在-1.0和1.0之间。这是正在失去一个很大的精度。 – 2012-08-08 20:43:21
从Codeplex获得BigRational。它是微软的Base Class Library的一部分,因此它是.Net的一项工作。一旦你的,然后做一些事情,如:
System.Numerics.BigInteger x = GetDividend() ;
System.Numerics.BigInteger y = GetDivisor() ;
BigRational r = new BigRational(x , y) ;
double value = (double) r ;
与必然溢/下溢/的精度,当然,另一个问题损失的处理。
既然你不能在BigRational库拖放到你的代码,显然,其他的办法是走出right algorithms book并推出自己的...
最简单的方法,当然,滚动”自己的“,因为有理数表示为两个整数的比率(除法),是从BigRational类抓取显式转换为双运算符并调整它以适应。我花了大约15分钟。
关于我所做的唯一重大修改是当结果为正数或负数零/无穷时,结果的符号如何设置。当我在它时,我将它转换为BigInteger
扩展方法为您:
public static class BigIntExtensions
{
public static double DivideAndReturnDouble(this BigInteger x , BigInteger y)
{
// The Double value type represents a double-precision 64-bit number with
// values ranging from -1.79769313486232e308 to +1.79769313486232e308
// values that do not fit into this range are returned as +/-Infinity
if (SafeCastToDouble(x) && SafeCastToDouble(y))
{
return (Double) x/(Double) y;
}
// kick it old-school and figure out the sign of the result
bool isNegativeResult = ((x.Sign < 0 && y.Sign > 0) || (x.Sign > 0 && y.Sign < 0)) ;
// scale the numerator to preseve the fraction part through the integer division
BigInteger denormalized = (x * s_bnDoublePrecision)/y ;
if (denormalized.IsZero)
{
return isNegativeResult ? BitConverter.Int64BitsToDouble(unchecked((long)0x8000000000000000)) : 0d; // underflow to -+0
}
Double result = 0 ;
bool isDouble = false ;
int scale = DoubleMaxScale ;
while (scale > 0)
{
if (!isDouble)
{
if (SafeCastToDouble(denormalized))
{
result = (Double) denormalized;
isDouble = true;
}
else
{
denormalized = denormalized/10 ;
}
}
result = result/10 ;
scale-- ;
}
if (!isDouble)
{
return isNegativeResult ? Double.NegativeInfinity : Double.PositiveInfinity;
}
else
{
return result;
}
}
private const int DoubleMaxScale = 308 ;
private static readonly BigInteger s_bnDoublePrecision = BigInteger.Pow(10 , DoubleMaxScale) ;
private static readonly BigInteger s_bnDoubleMaxValue = (BigInteger) Double.MaxValue;
private static readonly BigInteger s_bnDoubleMinValue = (BigInteger) Double.MinValue;
private static bool SafeCastToDouble(BigInteger value)
{
return s_bnDoubleMinValue <= value && value <= s_bnDoubleMaxValue;
}
}
谢谢。不幸的是,我不能在生产代码中使用BigRational,因为它处于测试阶段。论坛和书籍应该是答案。 – 2012-08-08 21:05:32
@RaheelKhan:或者您可以从BigRational库中去除显式转换运算符并根据需要进行修改。我花了大约15分钟(见我编辑的答案)。 – 2012-08-08 23:34:52
谢谢。考虑到替代方案,这可能是唯一的出路。在标记正确的答案之前,我会花一些时间来消化这个并进行测试。 – 2012-08-09 01:10:29
您需要它有多精确? – 2012-08-08 20:14:48
你正在处理的数字是什么。请显示数字的性质。 – MethodMan 2012-08-08 20:16:13
@AustinSalonen:精度越高越好,但即使精确到几位十进制数字也足以达到我想要的位置。 – 2012-08-08 20:20:11