zgadzam się z jmcnamara's prior answer. Ta odpowiedź rozszerza się na nią.
Dla każdego 64-bitowego binarnego numeru zmiennoprzecinkowego IEEE 754 istnieje zakres ułamków dziesiętnych, który zaokrąglałby się do niego na wejściu. Począwszy od -130,98999999999069, najbliższa reprezentowalna wartość to -130,989999999068677425384521484375. Poniżej rundy do najbliższej z okrągłymi regułami równymi połowie, wszystko w zakresie [-130.9899999999907009851085604168474674224853515625, -130,9899999999906725633991300128400325775146484375] zaokrągla do tej wartości. (Zakres jest zamknięty, ponieważ binarna reprezentacja liczby centralnej jest parzysta, jeśli byłaby nieparzysta, zakres byłby otwarty). Zarówno -130.98999999999069, jak i -130,9899999999907 są w zasięgu.
Masz taką samą liczbę zmiennoprzecinkową jak Excel. Masz tę samą liczbę zmiennoprzecinkową, która została wprowadzona do programu Excel. Niestety, kolejne eksperymenty sugerują, że Excel 2007 konwertuje tylko najważniejsze 15 cyfr danych wejściowych. Wkleiłem -130.98999999999069 do komórki Excel. Nie tylko był wyświetlany jako -130.98999999999, arytmetyka używająca go była zgodna z najbliższą podwójną do tej wartości, -130.989999999990004653227515518665313720703125, a nie oryginalną wartością wejściową.
Aby uzyskać taki sam efekt jak w programie Excel, może być konieczne użycie np. BigDecimal do obcięcia do 15 cyfr dziesiętnych, a następnie konwersji do podwójnego.
Domyślna konwersja ciągów Java dla wartości zmiennoprzecinkowych w zasadzie wybiera ułamek dziesiętny z najmniejszą liczbą miejsc dziesiętnych, które zostałyby zamienione z powrotem na pierwotną wartość. -130,9899999999907 ma mniej miejsc po przecinku niż -130,98999999999069. Wygląda na to, że program Excel wyświetla mniej cyfr, ale Apache POI uzyskuje jedną z reprezentacji tego samego numeru, co w Javie.
Oto program, którego użyłem do uzyskania liczb w tej odpowiedzi. Zauważ, że używam BigDecimal tylko do uzyskania dokładnych wydruków podwójnych i do obliczenia punktu środkowego pomiędzy dwoma kolejnymi debelami.
import java.math.BigDecimal;
class Test {
public static void main(String[] args) {
double d = -130.98999999999069;
BigDecimal dDec = new BigDecimal(d);
System.out.println("Printed as double: "+d);
BigDecimal down = new BigDecimal(Math.nextAfter(d, Double.NEGATIVE_INFINITY));
System.out.println("Next down: " + down);
System.out.println("Half down: " + down.add(dDec).divide(BigDecimal.valueOf(2)));
System.out.println("Original: " + dDec);
BigDecimal up = new BigDecimal(Math.nextAfter(d, Double.POSITIVE_INFINITY));
System.out.println("Half up: " + up.add(dDec).divide(BigDecimal.valueOf(2)));
System.out.println("Next up: " + up);
System.out.println("Original in hex: "+Long.toHexString(Double.doubleToLongBits(d)));
}
}
Oto jej wyniki:
Printed as double: -130.9899999999907
Next down: -130.989999999990715195963275618851184844970703125
Half down: -130.9899999999907009851085604168474674224853515625
Original: -130.98999999999068677425384521484375
Half up: -130.9899999999906725633991300128400325775146484375
Next up: -130.989999999990658352544414810836315155029296875
Original in hex: c0605fae147ae000
Mój problem to nie dokładność, to jak emulować interpretację liczby w Excelu. Używanie BigDecimal zachowuje numer podany w formacie pliku, ale nie zbliża mnie to do zachowania Excela. –
@DavidNorth Cóż, gdy już masz numer "BigDecimal", możesz go zaokrąglić do dowolnej liczby miejsc po przecinku (co widać w Excelu dla użytkownika, wydaje się, 11 miejsc dziesiętnych w twoim konkretnym przykładzie). Ogólnie rzecz biorąc, próba "symulowania zachowania Excela" nie jest drogą, jak sądzę;) –
Będę musiał dodać więcej przykładów, ale trudność, którą mamy, polega na tym, że nie ma jednego algorytmu do zaokrąglania, który możemy znaleźć przy użyciu BigDecimal, który pasuje do Excela we wszystkich przypadkach. Jeśli nie próbujesz symulować zachowania Excela: trudność polega na tym, że moi użytkownicy widzą liczbę w Excelu i chcą, żebym pokazał im ten sam numer podczas spożywania arkusza kalkulacyjnego. Nierozsądne z nich, nawet jeśli Microsoft robi wszystko, aby to uniemożliwić ... –