Dodawanie zmiennoprzecinkowe, bez pływaków!

9

Twoim zadaniem jest napisanie programu, w dowolnym języku, który doda dwie liczby zmiennoprzecinkowe razem BEZ, używając jakiejkolwiek matematyki ułamkowej lub zmiennoprzecinkowej. Matematyka liczb całkowitych jest dozwolona.

Format

Format liczb to ciągi zawierające jedynki i zera, które reprezentują wartość binarną 32-bitowej liczby zmiennoprzecinkowej IEEE 754 . Na przykład liczba 2,54 byłaby reprezentowana przez ciąg „01000000001000101000111101011100”.

Cel

Program powinien wprowadzić dwie liczby w wyżej wymienionym formacie, dodać je razem i wyprowadzić wynik w tym samym formacie. Najkrótsza odpowiedź w dowolnym języku wygrywa!

Zasady

Absolutnie nie są dozwolone funkcje zmiennoprzecinkowe, dziesiętne ani żadne inne funkcje matematyczne.

Możesz założyć, że dane wejściowe są czyste (tzn. Zawierają tylko 1 i 0).

Możesz założyć, że dane wejściowe są liczbami, a nie Inf, -Inf, NaN lub subnormalne. Jeśli jednak wynik jest większy niż wartość maksymalna lub mniejszy niż wartość minimalna, powinieneś zwrócić odpowiednio Inf i -Inf. Wynik nienormalny (denormalny) można spłukać do zera.

Zaokrąglanie nie jest konieczne. Nie martw się, jeśli Twoje wyniki są kilka bitów.

Testy

Aby przetestować swoje programy, możesz konwertować między liczbami binarnymi dziesiętnymi i zmiennoprzecinkowymi za pomocą tego narzędzia .

1000 + 0,5 = 1000,5

01000100011110100000000000000000 + 00111111000000000000000000000000 = 01000100011110100010000000000000

float.MaxValue + float.MaxValue = Nieskończoność

01111111011111111111111111111111 + 01111111011111111111111111111111 = 01111111100000000000000000000000

321,123 + -1123.321 = 197,802

01000011101000001000111110111110 + 11000010111101101010010001011010= 01000011010001011100110101010000

Powodzenia!

Hannesh
źródło

Odpowiedzi:

3

Python, 224 znaki

Ten kod konwertuje zmiennoprzecinkowe dane wejściowe fna liczbę całkowitą f*2^150, dokonuje dodania za pomocą natywnych dużych liczb całkowitych w języku Python, a następnie konwertuje z powrotem.

V=lambda x:((-1)**int(x[0])<<int(x[1:9],2))*int('1'+x[9:],2)
B=lambda x,n:B(x/2,n-1)+'01'[x&1]if n else''
def A(x,y):
 v=V(x)+V(y)
 s=e=0
 if v<0:s=1;v=-v
 while v>=1<<24:v/=2;e+=1
 if e>254:v=0
 return'%d'%s+B(e,8)+B(v,23)
Keith Randall
źródło
3

J (172 znaki)

Ponieważ IEEE 754 zezwala na pięć reguł zaokrąglania, wybrałem zasadę „w kierunku 0”. Oto mój kod:

b=:(_1&^)@".@{.*[:#.1x,("."0)@(9&}.),#.@:("."0)@}.@(9&{.)$0:
a=:b@[([:,(<&0)":"0@:,,@((8$2)&#:)@(-&24)@$@#:,}.@(24&{.)@#:@|)@(]`(**2x^278"_)@.((>&((2x^278)-2x^254))@|))@+b@]

Te same przykłady, które podajesz (ale nie dokładnie te same wyniki z powodu innej reguły zaokrąglania):

   '01000100011110100000000000000000' a '00111111000000000000000000000000'
01000100011110100010000000000000
   '01111111011111111111111111111111' a '01111111011111111111111111111111'
01111111100000000000000000000000
   '01000011101000001000111110111110' a '11000010111101101010010001011010'
01000011010001011100110101001111
Thomas Baruchel
źródło