Konwertowanie liczb dziesiętnych na ZM, U1 oraz U2.. Negacja

0

Witam
Bardzo was proszę o pomoc oraz wyrozumiałość, bo uczę się programowania w javie od dość niedawna.
Do zadania mam napisać program, który konwertuje wpisaną przez użytkownika liczbę dziesiętną na ZM, a w momencie gdy użytkownik wpisze wartość ujemną ma wypisać rzecz jasna "1.(wartość)". Dokładnie tak było w zadaniu. Potem program miał dodatkowo podaną wartość przekształcić na U1 oraz U2. W U1 gdy liczba jest ujemna to wg, licznych źródeł w internecie, które przeszukałem następuje negacja. Tak więc zrobiłem początkowo za pomocą pętli, pozamieniałem wszystkie jedynki na zera oraz zera na jedynki. Jednakże wpadłem na pomysł użycia negacji, bo to (przynajmniej tak mi się wydawało) powinno było mi ułatwić przekształcenia. Wyszukałem rzecz jasna "negacja=~negacja" z nadzieją, że to pomoże zwłaszcza, że jeśli to by działało to operacje na podobnych operatorach miałyby mi pomóc w przekształceniu na U2 oraz wykonywania działać na liczbach w systemie U1 oraz U2 w następnym etapie.
Rozumiem to tak, że dla liczby 125 przeliczonej przez program na 01111101 w U1 powinna zostać wyświetlona jako: 10000010. W moim programie wyświetla ją jako: 1111100. Gdzieś nawet tu wyczytałem, żeby pokombinować coś z dodaniem +1 do negowanej liczby, ale wtedy wychodzi mi normalna liczba 125 tylko z bitem znaku 1. Czyli właściwie nie zmieniło się nic.
Dodam jeszcze, że program na potrzeby zadania miał być wykonany za pomocą operacji dzielenia oraz modulo a wynik obliczeń miał być zapisywany do tablicy 32-elementowej, z której później miał być wczytywany. (Jest to generalnie ćwiczenie z tablic.)

package Konwerter;
import java.util.*;

public class Main {
	public static void main(String[] args) {
		Scanner in=new Scanner(System.in);
		int l=0, reszta=0;
		int[] binary=new int[32];
		int[] U1=new int[32];
		System.out.println("Program konwertujący liczbę dziesiętną na ZM.\nPodaj swoją liczbę.");
		int input=in.nextInt();
		int pomocnicza=input;
		int negacja=input;
		System.out.print("Liczba "+pomocnicza+" biarnie: ");
		while (input!=0){
			if (input<0){
				System.out.print("1.");
				input *=-1;
			}
																	
			reszta=input%2;
			input /=2;			
			binary[l]=reszta;			
			l++;
						
		}
		
			if(pomocnicza>0){
				System.out.print("0");
			}
		
			for (int i=l-1; i>=0; i--){
				System.out.print(binary[i]);
			}
			System.out.println();
			System.out.println("Przedstawienie luczby w reprezentacji U1:");
			
			if(pomocnicza>0){
				System.out.print("0");
				for (int i=l-1; i>=0; i--){
					System.out.print(binary[i]);
			}
			}
			
			
			negacja=~negacja;
			reszta=0;
			l=0;						
			while(negacja!=0){
				reszta=negacja%2;
				//System.out.print(reszta);
				negacja/=2;	
				U1[l]=reszta;	
				//System.out.print(U1[l]);
				l++;
				
			}
			System.out.println(l);
			for (int i=l-1; i>=0; i--){
				System.out.print(U1[i]);
			}
			
			
			
			/* if(pomocnicza<0){
				System.out.print("1.");
				for (int i=l-1; i>=0; i--){	
					if(binary[i]==1){
						binary[i]=0;
					}
						else if (binary[i]==0){
							binary[i]=1;
					}
						
					
					System.out.print(binary[i]);
				}
	*/
			}
		
		
		
		
	//}
	

}
 

Zdaję sobie, że jest tutaj generalnie bałagan oraz kilka niepotrzebnych zmiennych, jednakże pracuję nad ni od kilku godzin i zmieniam go na różne sposoby patrząc jak co będzie działać, więc zmienne i linijki kodu pozostawały, żebym w razie czego łatwiej miał jak do nich wrócić. Jeśli kiedykolwiek ogarnę ten program to wówczas jeszcze go uporządkuję tak, żeby nie pozostawało w nim nic niepotrzebnego.
Bardzo proszę o pomoc w zrozumieniu jak to działa i dla czego to nie działa tak jak ma działać oraz jak sprawić, żeby faktycznie tak działał. ;)
I jak już wcześniej wspomniałem proszę o wyrozumiałość, jestem dopiero na linii startu jeśli chodzi o mój poziom.

PS: To co poniżej widać w komentarzu to było zanim jeszcze pomyślałem o jakiejkolwiek negacji. Wówczas program faktycznie spełniał swoją rolę, jednakże nie jestem pewien czy mógłbym później wykonywać na programie wykonanym w taki sposób jakiekolwiek operacje jak dodawanie na takich liczbach.

0

Bez oszczędzania pamięci:

        int negacja = 0;
        byte[] U2 = new byte[32];
        byte[] ZM = new byte[32];
        byte[] U1 = new byte[32];
        for(int i=0;i<32;i++)
        {
            U2[31-i] = (byte)(liczba>>i & 1);
        }
        if(liczba < 0)
        {
            ZM[0] = 1;
            liczba*=-1;
            negacja = 1;
        }
        int i = 0;
        while(liczba > 0)
        {
            ZM[31-i] = (byte)(liczba % 2);
            liczba/=2;
            i++;
        }
        for(i=1;i<32;i++)
        {
            U1[i] = (byte)Math.abs(ZM[i] - negacja);
        }
        U1[0] = ZM[0];
        //dla kontroli
        System.out.println("U2: "+Arrays.toString(U2));
        System.out.println("ZM: "+Arrays.toString(ZM));
        System.out.println("U1: "+Arrays.toString(U1));

W systemach ZM i U1 nie zapiszesz liczby Integer.MIN_VALUE = -2147483648.
Dla ZM i U1 wykorzystałem dzielenie i operację modulo.
Dla U2 odczytałem po prostu reprezentacje bitową liczby - Java korzysta z postaci U2.

0

Pozwól, że przeanalizuję sobie tutaj każdą linijkę, żeby mieć pewność, że dobrze to rozumiem.
W sumie działania pierwszej linijki w ogóle nie rozumiem. " U2[31-i] = (byte)(liczba>>i & 1);" - Od przedostatniego indeksu w tablicy przesuwa bity w prawo i dodaje jedynkę?
Potem dla ujemnej liczby pierwszemu indeksowi [0] nadajesz wartość 1, mnożysz liczbę przez ujemną aby była dodatnia i nadajesz zmiennej negacja wartość 1.
Następnie wprowadzasz zmienną i, i dopóki liczba jest >0
dla każdego indeksu tablicy ZM od ostatniego przypisujesz resztę z dzielenia liczby.
W następnej pętli natomiast dla każdego indeksu ZM wyciągasz wartość bezwzględną i odejmujesz wartość negacji?

Ciężko mi pojąć jak to w ogóle działa. Napisałeś w kilku prostych i klarownych linijkach program, który ja rozpisałem na 50+ śmieciowych linijek który jeszcze nie działa jak trzeba. Mój program jest w takim razie do wyrzucenia. Niektórych rozwiązań jak np. [31-i] to ja nawet nie znałem.
Dzięki wielkie za pomoc.
Nie mam tylko pojęcia czy faktycznie mój program da się jeszcze uratować czy jest cały do "wymiany".

0

Wybaczcie za dopisek, ale nie mam tutaj konta wynikiem czego brak mi opcji edycji.
Wypróbowałem linijkę z U2 w swoim kodzie i wpadł mi kolejny problem.
Bo teraz nie wiem jak wyświetlić wynik przeliczenia na U2. W Twoim kodzie wyświetlam całą tablicę, a chciałbym wyświetlić to w sposób w jaki wyświetla u mnie, że wyświetla tylko te indeksy, którym przypisana jest odpowiednia wartość i nie więcej. A nie mogę teraz zrobić tego w taki sam sposób jak u siebie gdyż pętla wykonuje się 32 razy. Czyli i tak wyświetlam wszystkie elementy łącznie z tymi niepotrzebnymi. Jak więc z tego wybrnąć?

0

Jeśli i zmienia się od 0 do 31, to 31 - i zmienia się (malejąco) od 31 do 0. Takie odwrócenie jest potrzebne bo algorytmy tworzenia U2 i ZM generują bity w kolejności od najmniej znaczącego (wpierw dostaniemy ilość jedynek, którą powinniśmy zapisać ostatnim miejscu w tablicy).
Operator &, to logiczne AND na bitach:<tt>
13 = 0...01101
1 = 0....0001
13&1 = 0....0001
</tt>zatem n & 1 to najmniej znaczący bit liczby n, operator >> przesuwa bity w prawo, w szczególności po wykonaniu przesunięcia n >> 2, na najmniej znaczącej pozycji pojawi się ilość czwórek w liczbie n.
W kodowaniu U1 liczby ujemne uzyskujemy przez zanegowanie wszystkich bitów (1 -> 0, 0 -> 1). Ja skorzystałem z pomocniczej zmiennej negacja, która ma wartość 0 dla liczb dodatnich, 1 dla licz ujemnych, wzór 1 - negacja niczego nie zmienia dla liczb dodatnich, a dla ujemnych zmienia 1 w 0, a 0 w -1, dlatego dopisałem wartość bezwzględną.
Zdania

wyświetla tylko te indeksy, którym przypisana jest odpowiednia wartość i nie więcej
nie rozumiem, każdemu indeksowi przypisana jest przecież jakaś wartość, jeśli chodzi Ci o to by nie wypisywać wiodących zer to

int i = 0;
while(U2[i] == 0)
{
    i++;
}
while(i<U2.length)
{
    System.out.print(U2[i]);
    i++;
}
0

Wielkie dzięki, będę musiał to jeszcze na chłodno przeanalizować.
Sposób, który podałeś działa dobrze dla liczb dodatnich, ale dla ujemnych wyświetla mi już inaczej.

 System.out.println("\nPrezentacja liczby w systemie U2.");
			 
			 
			 for (int i=0; i<32; i++){
				 U2[31-i] = (byte)(pomocnicza >> i & 1);
				 
			 }
				 
			 int i=0;
			 while (U2[i]==0){
				 i++;
			 }
			 
			 while (i<U2.length){
			 System.out.print(U2[i]);
			 i++;
			 } 

dla wartości -15 wyświetla mi 11111111111111111111111111110001
Czemu tak się dzieje? Co robię źle?

0

Nic nie robisz źle, tak wygląda zapis liczby -15 typu int w systemie U2.

0

Czyli, żeby wyświetlało mi jakoś "po ludzku" czyli nie rozpisywało mi tego na 32 indeksach, tylko tak jak w przypadku U1 i ZM musiałbym zmienić typ wprowadzanej liczby na byte?

0

Tak, zmniejsz też wszystkie tablice i skróć pętle.

0

Pozmniejszałem typy wszystkich zmiennych (nawet w pętlach) i tablic na "byte", nie rozumiem tylko co masz na myśli mówiąc o skracaniu pętli.
Tak czy inaczej wynik wciąż pozostał niezmienny.

0
        byte[] U2 = new byte[8];
        for(int i=0;i<8;i++)
        {
            U2[7-i] = (byte)(liczba>>i & 1);
        }
0

Ahh teraz rozumiem wszystko, ale chyba w takim razie jestem skazany na 32 indeksowy wynik bo na potrzeby zadania tablice muszą pozostać 32 elementowe.
Tak czy inaczej wielkie dzięki za pomoc i cierpliwość. Bo ten program faktycznie mnie zagiął. Mam nadzieję, że zdołam nauczyć się więcej i wówczas wrócę do tego zadania ponownie i spróbuję go napisać w inny mniej pogmatwany sposób niż dzisiaj.

1 użytkowników online, w tym zalogowanych: 0, gości: 1