2013-01-11 12 views
6

Istnieją dwa wektory o różnych, ale powiązanych rozmiarach. Im większy jest (2 * RESOLUTION) + INDEX_OFFSET (na przykład 2050), a mniejszy to po prostu RESOLUTION (np. 1024). Uważam, że jest wystarczająco bezpieczny, aby założyć, że uint16_t może być użyty do przechowywania indeksu wektorowego.Przy liczbach całkowitych C++, czy 1 dzieli się przez 2 niezawodnie równe 0 i 3/2 = 1, 5/2 = 2 itd.?

Iteracja przez większy wektor jest wykonywana poprzez zwiększenie numeru resultIndex o 2. Podczas każdej iteracji następuje przypisanie do mniejszego wektora o indeksie (resultIndex - INDEX_OFFSET)/2.

Zasadniczo kod opiera się na założeniu, że niezależnie od tego, czy INDEX_OFFSET jest nieparzysta czy parzysta, powyższy podział przez 2 będzie zawsze zaokrąglany w dół, niezależnie od architektury. Na przykład, jeśli resultIndex ma wartość 0 lub 1, oczekiwane jest 0, jeśli jest to 2 lub 3, wówczas oczekiwane jest 1 i tak dalej. Czy jest to bezpieczne założenie w ramach powyższych parametrów?

N.B. Przyjmuję do wiadomości istnienie 'Dividing integer types - Are results predictable?', ale nie wydaje się to być dokładnie zgodne.

+3

jak zawsze '2 + 2 = 5' w bardzo dużych przypadkach 2 – Woot4Moo

+4

@ Woot4Moo: snarky może być zabawą, ale w tym przypadku jest po prostu głupi. Podział całkowy ma bardzo szczegółowe reguły dotyczące obcinania, a faktem jest, że '3/2 == 1'. –

Odpowiedz

15

Tak; gwarantuje to języków:

[C++11: 5.6/4]: binarny / operatora daje iloraz oraz binarnego % operator otrzymuje się resztę z dzielenia pierwszej ekspresji przez drugą. Jeśli drugi operand z / lub % jest równy zero, zachowanie jest niezdefiniowane. Dla integralnych operandów operator / daje iloraz algebraiczny z odrzuconą częścią ułamkową;, jeśli iloraz a/b jest reprezentatywny w typie wyniku, (a/b)*b + a%b jest równy a.

W 3/2 zarówno 3 i 2 są integralnymi argumenty; algebraiczny iloraz tej operacji to 1.5, a po odrzuceniu części ułamkowej .5 otrzymujesz 1. Dotyczy to innych przykładów i, no cóż, wszystkich innych przykładów.

+1

Doskonale, dziękuję! – mosi

+1

+1, i dzięki Bogu to jest standardowe. Nie potrafię * wyobrazić sobie * ilości wymyślonego kodu tam, gdzie nie było. – WhozCraig

+2

Uwaga: na linux => 'signal 5: wyjątek arytmetyczny' jest zwykle wynikiem podziału przez' 0', który jest * wykonywany * ... chociaż ponieważ kompilator może zoptymalizować kod przy założeniu, że dzielnik nie jest ' 0 ', mogą się dziać dziwne rzeczy (inaczej "niezdefiniowane zachowanie"). –

Powiązane problemy