Binärzahlen Umrechner mit Batch programmieren?

4 Antworten

Vom Fragesteller als hilfreich ausgezeichnet

Mit Batch kenne ich mich nicht so gut aus.

Ich kann dir aber den Algorithmus erklären. Nennen wir die Dezimalzahl : = x

  1. Du teilst x durch 2
  2. Das Ergebnis wird dein neues x
  3. Den Rest schreibst du an den Anfang deiner Ergebniszeichenkette
  4. Weiter mit 1

Das Ganze machst du solange , bis x=0 ist.

So weit ich weiß ist %% der Modulo-Operator.

Wie man Batch-Schleifen programmiert weiß ich nicht.

Woher ich das weiß:Berufserfahrung – Studium der Informatik + Softwareentwickler seit 25 Jahren.

Erzesel  05.10.2019, 04:43

Das funktioniert nur mit positiven Zahlen! 😤

0
Brainchild  05.10.2019, 08:09
@Erzesel

Stimmt, ich bin von positiven Zahlen ausgegangen.  fragfelix12 hat darüber nichts geschrieben. Dafür eignet sich mein Algorithmus auch für Systeme die keine Zweierpotenzen sind.

1

erstmal auf die "harte" Tour. Batch pur:

@echo off
setlocal EnableDelayedExpansion
chcp 65001 >nul & rem Umlaute  richtig darstellen.
:start
set /p "__Input= Bitte  eine Zahl eingeben eingeben : "
  rem prüfen ob eine gültige Zahl eingegeben wurde
set /a "__dummy=__Input+0" 2>nul
if "%__dummy%" neq "%__Input%" (
    echo "%__Input%" ist keine zulässige Zahl ^( -2147483648..2147483647^)
    set "__Input="
    goto :Start
)


  rem die Problematik bei  negativen Integern  ist diese binär  "richtig" darzustellen...
  rem der "Teileralgoritmus" funktioniert nur mit positiven Zahlen!  (-5 würde -10-1 ausspucken...:p)
  rem um für die Brechnung die Zahl  positiv  zu halten addiere ich die negative Zahl (Subtraktion) zum/vom max Integer (Positiv) binär 01111111111111111111111111111111= 2.147.483.647 und korrigiert  um plus 1 
  rem (wer jetzt häääää???? denkt,warum nicht einfach das Vorzeichen löschen? hat Binärmathematik  noch nicht begriffen....)
  rem egal ,damit sind wir das Vorzeichenbit los )
  rem klingt wie Irrsinn, aber  Batch "vertägt" keine Zahlen kleiner -2147483648 größer 2147483647 also muss man etwas zaubern...
if %__Input% geq 0 (
    set "__Number=%__Input%"
) else (
      rem ...das Mathematik ist ja so toll aber beim programmieren mit 32BitInteger wäre 2147483648 + __Input ein Fehler!!!!
      rem darum erst nach der Subtraktion 1 addieren!
    set /a "__Number=2147483647 + __Input + 1"
)
set "__Binary="


:Dec2Bin
  rem Modulooperation der eingegebenen Zahl mit 2 ergibt einen rest 0 oder 1, anschließend die eingegebene Zahl durch zwei Teilen (für einen eventuellen  nächsten Durchlauf)
  rem set /a  kann mehrere Operationen in einem Aufruf ausführen... (schneller)
set /a "Digit=__Number %% 2,__Number /= 2"
  rem schreibe das neue Digit vor das vorherige...
set __Binary=%Digit%%__Binary%
  rem solange die Schleife ausführen, bis nur noch 0 beim Teilen übrig ist.
if %__Number% neq 0 goto :Dec2Bin
  rem wenn %__Input% kleiner 0 war... 
if %__Input% lss 0 (
      rem ...mindestens 30 Nullen voranstellen
    set "__Binary=0000000000000000000000000000000%__Binary%"
      rem ...nur die letzten 31 Zeichen verwenden und eine 1 voranstellen (damit sind es 32 bit)
    set "__Binary=1!__Binary:~-31!"
)
echo Decimal: %__Input% =  Binary: %__Binary%
echo  Wieder  zurückkonvertieren:
  Rem und das Ganze  wieder  zurück nach Dezimal
set "__dummyBin=%__Binary%"
set "__Decimal="
for /L %%i in (1,1,32) do (
    if defined __dummyBin (
        set /a "__Decimal=(__Decimal<<1)|!__dummyBin:~0,1!"
        set "__dummyBin=!__dummyBin:~1!"
    )
)
echo %__Decimal%
goto start

...Wenn Dir jetzt die Haare zu Berge stehen und das Hirn ausbrennt... , dann kann ich Dir Trost spenden...

...es geht auch anders...

Mit Batch hat man auch die Möglichkeit andere Progamme die Arbeit erledigen zu lassen. ...und Powershell ist auch auf jedem Windows "eingebaut" und erlaubt den direkten Aufruf von Befehlen/Cmdlets über seine Kommandozeile.

...Also einfach munter https://docs.microsoft.com/de-de/dotnet/api/system.convert.tostring?view=netframework-4.8#System_Convert_ToString_System_Int16_System_Int32_

die Arbeit machen lassen:

@echo off
chcp 65001 >nul 
:start
set /p "__Input= Bitte  eine Zahl eingeben eingeben : "
set /a "__dummy=__Input+0" 2>nul
if "%__dummy%" neq "%__Input%" (
    echo "%__Input%" ist keine zulässige Zahl ^( -2147483648..2147483647^)
    set "__Input="
    goto :Start
)

  rem    Powershell -c "&{[convert]::ToString(%__Input%,2)}"     der variable %__Binary% zuweisen...
for /f %%a in ('Powershell -c "&{[convert]::ToString(%__Input%,2)}"') do (
    set "__Binary=%%a"
)

echo Decimal: %__Input% =  Binary: %__Binary%

echo  Wieder  zurückkonvertieren:
for /f "usebackq" %%a in (`Powershell -c "&{[convert]::ToInt32('%__Binary%',2)}"`) do (
    set "__Decimal=%%a"
)

echo %__Decimal%
goto start

Wenn es so einfach geht, warum dann das Monster?....

Weil ich's kann? und es gibt durchaus Situationen wo man wissen sollte wie es auch ohne vorgefertigte Funktionen klappt.

Mit der ersten Variante kannst Du auf jeden Fall ein gewisses Renommee ernten...

Woher ich das weiß:eigene Erfahrung – Ich mach das seit 30 Jahren

2.Anlauf:

...noch mal Pure Batch:

...auch ohne Powershell ,in pure Batch get es immer noch etwas eleganter...

... es wird per logischem AND 1 das niedrigste Bit abgefragt und die Eingangszahl um 1 Bit nach rechts geschoben (entspricht n/2 ist aber schneller). Nach höchstens 32 Schleifendurchläufen hat man alle nötigen Bits. Es geht also ganz ohne die Frickelei mit Modulo und Division... und damit auch ohne die Stringoperationen...

@echo off
setlocal EnableDelayedExpansion
chcp 65001 >nul & rem Umlaute  richtig darstellen.
:start
set /p "__Input= Bitte  eine Zahl eingeben eingeben : "
  rem prüfen ob eine gültige Zahl eingegeben wurde
set /a "__dummy=__Input+0" 2>nul
if "%__dummy%" neq "%__Input%" (
    echo "%__Input%" ist keine zulässige Zahl ^( -2147483648..2147483647^)
    set "__Input="
    goto :Start
)
set "__Number=%__Input%"
set "__Binary="
  for /l %%a in (1,1,32) do (
    rem  zum debugen: echo !__Number!
      rem Digit n AND 1 , 1Bit Nach rechts schieben 
    set /a "Digit=__Number & 1 ,__Number>>=1"
    set "__Binary=!Digit!!__Binary!"
    if !__Number! equ 0 goto :break
)
:break
echo Decimal: %__Input% =  Binary: %__Binary%


echo  Wieder  zurückkonvertieren:
set "__dummyBin=%__Binary%"
set "__Decimal="
for /L %%i in (1,1,32) do (
    if defined __dummyBin (
        set /a "__Decimal=(__Decimal<<1)|!__dummyBin:~0,1!"
        set "__dummyBin=!__dummyBin:~1!"
    )
)
echo %__Decimal%
goto start
pause

...manche Idee braucht eben etwas mehr Zeit um zu wachsen...🤓😏

..gefällt mir rein technisch sogar besser als die Powershellvariante

Woher ich das weiß:eigene Erfahrung – Ich mach das seit 30 Jahren

Hier wäre mein Vorschlag:

@echo off
:main
    set "result="
    set /p "num_0=Dezimalzahl: >"

    call :deleteLeadingZero %num_0%
    set /a num_0  = %errorlevel%
    set /a number = %num_0%

    :do_while
        set /a number = %number% /  2
        set /a binary = %number% %% 2
        set   "result=%binary%%result%"
    if %number% NEQ 0 goto do_while

    echo %num_0% in binaer: %result% &echo+
goto main

:deleteLeadingZero
exit /B %~1

Hier ist der Link zu dem Skript auf GitHub: https://github.com/timlg07/Batch_Tools/blob/master/1-1-int2binary.bat

Habe zu jedem Skript eine Erklärung, auch wenn die Bedienung dieses Skriptes recht trivial ist: https://github.com/timlg07/Batch_Tools/blob/master/1-1-int2binary.txt

Wenn die Batch Teil eines größeren Programmes sein soll und Zahlen jeder Art konvertieren soll, musst du negative Zahlen im Voraus abfangen und eigens behandeln.

Woher ich das weiß:eigene Erfahrung