浮动精度损失
Loss of accuracy with floats
我正在尝试计算浮点数的总和。所有小数字都正确输出,当我使用非常大的数字作为输入时,输出总是关闭几个整数。例如,H = 5764801 W = 1679616,在纸面上计算为 335923 30275911。但是在我的程序中,打印了 335923 30275908 。这是代码:
public void printOutput(int H, int W) // The inputs
{
if(H == 1 && W == 1)
{
System.out.println(0 + " " + 1);
return;
}
List<Integer> pfw = primeFactors(W);
int y = 1;
while(H != (int) (Math.pow(Math.pow(W, 1f/y) + 1f, y))) y++;
final float N = findWholeNumber(pfw);
float height = 0;
for(int x = 1; x <= y + 1; x++)
{
height += (float) (W * Math.pow((N + 1f) / N, x-1f) + 1e-8); //Here is the summation
}
float cats = 1;
for(int x = 2; x <= y + 1; x++)
cats += (float) (Math.pow(N, x-1));
int notWorking = (int) (cats - W);
System.out.println(notWorking + " " + (int)height); //Outputs printing
}
private int findWholeNumber(List<Integer> factors)
{
List<Integer> common = new ArrayList<Integer>();
for(int i = 0; i < factors.size(); i++)
{
if(common.contains(factors.get(i))) continue;
common.add(factors.get(i));
}
int num = common.get(0);
for(int i = 1; i < common.size(); i++)
num *= common.get(i);
return num;
}
private List<Integer> primeFactors(int num)
{
List<Integer> pf = new ArrayList<Integer>();
if(num == 1)
{
pf.add(1);
return pf;
}
for(int j = 2; j <= num; j++)
while(num % j == 0) // is prime
{
pf.add(j);
num /= j;
}
return pf;
}
}
浮点数的精度有限,因为尾数的宽度有限。
你可以尝试 double
你的情况,哪个精度更高(因为它的尾数更宽),但它也是有限的。
更多信息:https://en.wikipedia.org/wiki/IEEE_floating_point#IEEE_754-2008 and What is the maximum number in the mantissa part of a Java float?
如果您需要无限精度,请尝试BigDecimal
。有效数字的数量仅受您的内存量限制。
如果您只需要整数值,BigInteger
是一个选项。
研究 每位计算机科学家应了解的浮点运算知识,David Goldberg,1991 年。
https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
我正在尝试计算浮点数的总和。所有小数字都正确输出,当我使用非常大的数字作为输入时,输出总是关闭几个整数。例如,H = 5764801 W = 1679616,在纸面上计算为 335923 30275911。但是在我的程序中,打印了 335923 30275908 。这是代码:
public void printOutput(int H, int W) // The inputs
{
if(H == 1 && W == 1)
{
System.out.println(0 + " " + 1);
return;
}
List<Integer> pfw = primeFactors(W);
int y = 1;
while(H != (int) (Math.pow(Math.pow(W, 1f/y) + 1f, y))) y++;
final float N = findWholeNumber(pfw);
float height = 0;
for(int x = 1; x <= y + 1; x++)
{
height += (float) (W * Math.pow((N + 1f) / N, x-1f) + 1e-8); //Here is the summation
}
float cats = 1;
for(int x = 2; x <= y + 1; x++)
cats += (float) (Math.pow(N, x-1));
int notWorking = (int) (cats - W);
System.out.println(notWorking + " " + (int)height); //Outputs printing
}
private int findWholeNumber(List<Integer> factors)
{
List<Integer> common = new ArrayList<Integer>();
for(int i = 0; i < factors.size(); i++)
{
if(common.contains(factors.get(i))) continue;
common.add(factors.get(i));
}
int num = common.get(0);
for(int i = 1; i < common.size(); i++)
num *= common.get(i);
return num;
}
private List<Integer> primeFactors(int num)
{
List<Integer> pf = new ArrayList<Integer>();
if(num == 1)
{
pf.add(1);
return pf;
}
for(int j = 2; j <= num; j++)
while(num % j == 0) // is prime
{
pf.add(j);
num /= j;
}
return pf;
}
}
浮点数的精度有限,因为尾数的宽度有限。
你可以尝试 double
你的情况,哪个精度更高(因为它的尾数更宽),但它也是有限的。
更多信息:https://en.wikipedia.org/wiki/IEEE_floating_point#IEEE_754-2008 and What is the maximum number in the mantissa part of a Java float?
如果您需要无限精度,请尝试BigDecimal
。有效数字的数量仅受您的内存量限制。
如果您只需要整数值,BigInteger
是一个选项。
研究 每位计算机科学家应了解的浮点运算知识,David Goldberg,1991 年。 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html