Drugie pytanie, które zadajesz, dotyczy rozmiaru ulp w Javie.
Jeśli wartość parametru ulp przekracza 1/(n)
, zaokrąglenie w mnożeniu nie spowoduje odzyskania pierwotnej podzielonej wartości int. Zazwyczaj większe uniesienia są powiązane z większymi podwójnymi wartościami. Zęby powiązane z podwójnym zaczynają przekraczać 1 około 9E15; jeśli twoje odzyskane debile były w pobliżu, możesz znaleźć problemy z round() nie otrzymaniem oczekiwanej odpowiedzi. Ponieważ pracujesz z wartościami int, największą wartością licznika twojego podziału będzie Integer.MAX_VALUE
.
następujących testów programowych wszystkie pozytywne wartości całkowite z n
aby zobaczyć, który powoduje, że największy potencjał do zaokrąglania błąd podczas próby odzyskania podzielony int:
public static void main(String[] args)
{
// start with large number
int m = Integer.MAX_VALUE;
double d = 0;
double largestError = 0;
int bigErrorCause = -1;
for (int n = 1; n < Integer.MAX_VALUE; n++)
{
d = (double) m/n;
double possibleError = Math.ulp(d) * n;
if (possibleError > largestError)
{
largestError = possibleError;
bigErrorCause = n;
}
}
System.out.println("int " + bigErrorCause + " causes at most "
+ largestError + " error");
}
Wyjście:
int 1073741823 powoduje nie więcej niż 4.768371577590358E-7 error
Zaokrąglanie przy użyciu Math.round, a następnie rzutowanie na int powinno odzyskać pierwotną int.
Nie głupie pytanie; pytanie rodzi pewne subtelne kwestie dotyczące arytmetyki zmiennoprzecinkowej i "odzyskiwalności" liczb całkowitych. – Nayuki
Wiele pytań zmiennoprzecinkowych na tej stronie ostatnio - hmm ... –