2013-08-05 12 views
23

mamCel iOS celu C Uzyskanie wartości liczbowej zaokrąglenia o wartości 2 miejsc po przecinku?

float a = 1412.244019; 

i potrzebuję być zaokrąglane do najbliższego drugiego miejsca po przecinku jak 1412.24000000. Rozumiem, że jeśli chcę przedstawić tylko dwa miejsca po przecinku, używam% .2f, ale tak NIE jest. Potrzebuję nowego z powodów matematycznych jako float.

Próbowałem kilka metod znaleziono na stackoverflow bez powodzenia. Bardziej oczywiste, którego używałem, wspomnę o tym poniżej, ale wciąż nie miałem szczęścia. Czy widzisz, dlaczego magia się nie dzieje?

PS: To robi pożądany efekt czasami, nie zawsze, który trafia mi do myślenia ... hmmm ...

góry dziękuję.

Kod:

float a = 1412.244019; 
NSLog(@"a is %f", a); //output a is 1412.244019 
a = [[NSString stringWithFormat:@"%.2f", a] floatValue]; 
NSLog(@"a is %f", a); //output a is 1412.239990 

EDIT:

Wygląda na to, kiedy używam pływaka po powyższej operacji, to biorąc pod uwagę, że jest 1412.240000 eventhough NSLog mówi inaczej ... dziwne. ale jestem coraz to, co chcę, więc Kudos dla straconego czasu ściga nic :)

EDIT chciałbym wybrać jak was wszystkich poprawnych odpowiedzi, ale skoro mogę wybrać tylko jedną, i wybrał pierwszą dobrą odpowiedź z dodatkowym wyjaśnieniem (z dwóch ostatnich).

Odpowiedz

49

Czy próbowałeś tego?

CGFloat val = 37.777779; 

CGFloat rounded_down = floorf(val * 100)/100; /* Result: 37.77 */ 
CGFloat nearest = floorf(val * 100 + 0.5)/100; /* Result: 37.78 */ 
CGFloat rounded_up = ceilf(val * 100)/100;  /* Result: 37.78 */ 

źródło: Rounding Number to 2 Decimal Places in C

Uzupełniając: Po prostu nie mają kontroli o tym, jak komputer będzie przechowywać wartość pływaka.

Tak więc te zaokrąglone wartości mogą nie być DOKŁADNIE "oczywistymi" wartościami dziesiętnymi, ale będą bardzo bliskie i to jest maksymalna gwarancja, jaką będziesz mieć.

+0

Wypróbowałem ją, Widziałem, że opublikowałeś tę metodę w innym poście. Ale NSLog wciąż daje tę samą odpowiedź (spróbuj sam). Ale zobacz EDIT powyżej. Mimo że NSLog podaje "zły" format, używa go poprawnie. –

+0

Tak jak powiedziałem w edycji, niemożliwe jest uzyskanie pełnej precyzji w punktach float –

+0

Rozumiem. Oblicza to tak, jak chcę. Po prostu myślę, że to dziwne, bo wtedy nigdy nie będziesz w stanie użyć precyzyjnej arytmetyki? –

2

Można pomnożyć a przez 100,0 i być może dodać 0,5 do zaokrąglenia, a następnie przyjąć wartość int wyniku. Następnie można użyć parametru/100, aby uzyskać wartość przed kropką dziesiętną, a% 100, aby uzyskać dwa miejsca dziesiętne.

+0

Próbowałem to zrobić bez powodzenia. Zobacz edycję powyżej (w ciągu dwóch minut) –

2

Nie można wymusić wartości zmiennoprzecinkowej. Pływaki mają być nieco przybliżone, ponieważ ich wielkość może być świetna, a ponieważ masz tylko tyle bitów do użycia, może się zbliżyć, ale nie dokładnie wyrazić liczby dziesiętnej.

Jedną z sugestii jest wykonanie całej arytmetyki w liczbie całkowitej, pomnożenie przez 100, a następnie podzielenie, kiedy chcesz wyświetlić ostateczny wynik. Możesz mieć zbyt duże liczby, które by to uniemożliwiły.

+0

Doceniam twoją odpowiedź i myślę, że będę musiał znaleźć inny sposób. Ale zobacz EDIT powyżej. Mimo że NSLog podaje "zły" format, używa go poprawnie. –

+0

NSLog mówi ci prawdę ... ale prawdopodobnie używasz innego formatowania/arytmetyki, która jest równoważeniem (tak jak zaprojektowano arytmetykę zmiennoprzecinkową), aby zbliżyć się do prawdziwej odpowiedzi. Ale przekonasz się, że czasami robi to, czego się spodziewasz, a czasami ma te końcowe znaki dziesiętne, których nie powinno tam być, lub liczba jest krótka. Jest najbardziej wyraźny, gdy idziesz do drukowania odpowiedzi, lub jeśli próbujesz porównać dwie liczby zmiennoprzecinkowe (to znaczy 2.0! = 5.0 - 3.0). Jeśli potrzebujesz dokładnej, precyzyjnej arytmetyki, aby zawsze być w prawo do 2 miejsc dziesiętnych, powinieneś użyć liczby całkowitej jak powyżej i/100. –

5

Najbliższa wartość do 1412.24 niż float to 1412.239990234375. Istnieje operacja no, która może wytworzyć wartość float, ponieważ format obiektów float nie reprezentuje żadnych bliższych wartości. Pytanie o reprezentowanie 1412.24 w float jest jak pytanie o podanie 2,5 w int. Po prostu nie da się tego zrobić.

Możliwości radzenia sobie z tym obejmują:

  • Można użyć formatowania użytku, który wyświetla „1412.24”, bez wprowadzania zmian do podstawowych float obiekt.
  • Możesz użyć double, aby zbliżyć się (dużo bliżej), ale nadal nie będzie to dokładnie 1412.24.
  • Można przeskalować wartości float do reprezentowalnych wartości (np. Zmierzyć w innych jednostkach, aby żądane wartości były dokładnie odwzorowywane w float).
  • Można użyć innego rodzaju danych, na przykład NSDecimal.
+0

Doceniam twoją odpowiedź i myślę, że będę musiał znaleźć inny sposób. Ale zobacz EDIT powyżej.Mimo że NSLog podaje "zły" format, używa go poprawnie. Zobaczę, czy uda mi się uzyskać lepsze wyniki przy użyciu jednej z wyżej wymienionych metod. –

+1

@ B-Man, typ C 'float' NIE MOŻE obiecać idealnego zaokrąglenia. Jeśli tego potrzebujesz, użyj innego typu danych. Możesz Rzuć własną i zachowaj wartość w wartości NSInteger równej 100, lub możesz użyć innego typu danych, na przykład [NSDecimal] (https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation /Classes/NSDecimalNumber_Class/Reference/Reference.html) wymienionych powyżej. – bshirley

10

to zrobić w Objective-C, dokładnie tak samo, jak w C:

double notRounded = ...; 
double rounded = round (notRounded * 100.0)/100.0; 

nie należy używać pacy - chyba można wytłumaczyć komuś dokładnie tym, co konkretne powody są w użyciu pacy ponad podwójne. Pływak ma bardzo ograniczoną precyzję. I używanie stropu lub podłogi jest głupie, ponieważ istnieje idealnie cienka standardowa funkcja o nazwie "runda".

Ani float, ani double can dokładnie reprezentują najbardziej wartości dziesiętne, jak 12,24. Ponieważ ma znacznie wyższą precyzję, podwójne pozwoli ci zbliżyć się znacznie do 12.24. Dlatego istnieje ogromna szansa, że ​​NSLog wyświetli jakąś dziwną liczbę dla (float) 12.24, jak 12.23999997394 lub coś podobnego, podczas gdy może wyświetlać 12.24 dla podwójnego.

+1

Dzięki za odpowiedź. Podwójna jest wtedy droga. Wybrałem już odpowiedź jakiś czas temu, więc myślę, że mogę tylko odpowiedzieć na twoje pytanie. Dziękuję za poświęcony czas na wyjaśnienia, bardzo doceniam. –

1

błąd w tej linii

a = [[NSString stringWithFormat:@"%.2f", a] floatValue]; 

prawidłowego jej

a = [NSString stringWithFormat:@"%.02f", a]; 
Powiązane problemy