hallo,
ich suche eine zuverlässige BitShift Funktion, die mit Unsigned-Integer's und großen Zahlen klarkommt (also wie in anderen sprachen eben auch).
Hab mir schon unzählige workaround-funktionen heruntergeladen, aber keine macht das was sie soll.
hallo,
ich suche eine zuverlässige BitShift Funktion, die mit Unsigned-Integer's und großen Zahlen klarkommt (also wie in anderen sprachen eben auch).
Hab mir schon unzählige workaround-funktionen heruntergeladen, aber keine macht das was sie soll.
Ich bin ein wenig verwirrt, die BitShift Funktion in AutoIt tut genau das was man vermuten würde oder?
Poste doch bitte ein Skriptbeispiel das dein Problem reproduzieren kann (z.B. BitShift(abc, x) = 123, sollte aber eigentlich 234 sein). Dann kann man auch was damit anfangen und eine Lösung finden
M
Ich bin ein wenig verwirrt, die BitShift Funktion in AutoIt tut genau das was man vermuten würde oder?
Er meint sicher Zahlen, die mit INT nicht mehr darstellbar sind... das Thema hatten wir vor kurzem... im Anhang ist die UDF, die ich dafür benutze.
_BitShift64(), _BinaryShift()
PS: Dies ist eine leicht geänderte Version der UDF, die von @Ward stammt.
; =============================================================================
; AutoIt Binary UDF (2011.9.15)
; Purpose: Functions About Binary Type Variable Management
; Author: Ward
; Modified by: Bitnugger
; 1. Unused variables commented out
; _BinaryReplace(): $BinaryLen, $SearchLen, $ReplaceLen
; _BinaryRandom(): $Ret
; 2. Number of parameters changed for _BitXOR64(), _BitAND64() and _BitOR64()
; From 20 to 255
; 3. Change the Code in _BinaryAnd, _BinaryOR, _BinaryXOR, _BinaryNot,
; _BinaryShift, _BinaryRotate, _BinaryReverse, _BinaryInBin, _BinaryReplace,
; _BinaryRandom
; From:
; Static $CodeBufferPtr
; If Not $CodeBufferPtr Then
; Local $Code
; If @AutoItX64 Then
; $Code = Binary("0x...")
; Else
; $Code = Binary("0x...")
; EndIf
; $CodeBufferPtr = __BinaryCodeBufferAlloc($Code)
; EndIf
; To:
; Local Static $aCode = ["0x...(X86)", "0x...(X64)"], _
; $CodeBufferPtr = __BinaryCodeBufferAlloc($aCode[@AutoItX64])
; =============================================================================
Alles anzeigen
Er meint sicher Zahlen, die mit INT nicht mehr darstellbar sind... das Thema hatten wir vor kurzem... im Anhang ist die UDF, die ich dafür benutze.
Wollte ich auch gerade vorschlagen .
Die UDF stammt vom User Ward aus dem engl. Forum : Binary UDF - Ward
Hast Du dort irgendwelche Änderungen vorgenommen ?
Die UDF's unterscheiden sich, obwohl in beiden Headern :
; =============================================================================
; AutoIt Binary UDF (2011.9.15)
; Purpose: Functions About Binary Type Variable Management
; Author: Ward
; =============================================================================
steht.
EDIT :
Die Funktionen _BitXOR64, _BitAND64 und _BitOR64 wurden von Bitnugger erweitert. Es können nun 255 Parameter übergeben werden (anstatt 20) - siehe Beitrag #6. (EDIT - Ende)
Mit "... das Thema hatten wir vor kurzem" meinst Du wahrscheinlich : Zahlen größer 64-Bit , oder ?
Gruß Musashi
EDIT: habe die zwei letzten Antworten erst nach meinem post gesehen, versuche das gleich mal .. danke!
... und ich habe es mit der Binary.au3 (obere) problemlos hinbekommen!!!
Danke für die Hilfe!!!
Hast Du dort irgendwelche Änderungen vorgenommen ?
Ja, habe ich.
In dem Script, in dem ich die UDF verwende, benutze ich die AutoIt3Wrapper-Direktive:
#AutoIt3Wrapper_AU3Check_Parameters=-q -d -w 1 -w 2 -w 3 -w- 4 -w 5 -w 6 -w- 7
Mit der Original-UDF bricht das Script dann mit Fehlermeldungen ab, weil die Variablen in den Zeilen 408-410 nicht verwendet werden. Deshalb habe ich die Zeilen auskommentiert - ähnlich auch in Zeile 487, wegen dem $Ret.
Die Funktionen _BitXOR64, _BitAND64 und _BitOR64 habe ich so umgestrickt, dass anstatt 20 Parameter nun 255 übergeben werden können, so wie es bei BitXOR usw. in AutoIt ist.
Alles anzeigenFrage von Musashi : "Hast Du dort irgendwelche Änderungen vorgenommen ?"
Ja, habe ich.
In dem Script, in dem ich die UDF verwende, benutze ich die AutoIt3Wrapper-Direktive:
#AutoIt3Wrapper_AU3Check_Parameters=-q -d -w 1 -w 2 -w 3 -w- 4 -w 5 -w 6 -w- 7
Mit der Original-UDF bricht das Script dann mit Fehlermeldungen ab, weil die Variablen in den Zeilen 408-410 nicht verwendet werden. Deshalb habe ich die Zeilen auskommentiert - ähnlich auch in Zeile 487, wegen dem $Ret.
Die Funktionen _BitXOR64, _BitAND64 und _BitOR64 habe ich so umgestrickt, dass anstatt 20 Parameter nun 255 übergeben werden können, so wie es bei BitXOR usw. in AutoIt ist.
Alles klar, die Erhöhung der Parameteranzahl von 20 auf 255 ist natürlich ein Gewinn.
Ich wage kaum zu fragen , aber könntest Du Dich mit der Idee anfreunden im Header deiner UDF einen Modified-Eintrag zu machen, z.B. :
; ===================================================================================
; AutoIt Binary UDF (2011.9.15)
; Purpose: Functions About Binary Type Variable Management
; Author: Ward
;
; Modified by Bitnugger :
; _BitXOR64, _BitAND64 and _BitOR64 now allow 255 parameters to be set instead of 20
; ===================================================================================
(einen Timestamp fügst Du ja bereits automatisch ein)
Da wir gerade bei dem User Ward sind :
Kennst Du oder sonst jemand die Hintergründe, warum Ward alle seine Skripte aus dem engl. Forum gelöscht hat ? Da waren wirklich geniale Sachen dabei.
Gruß Musashi
Ich wage kaum zu fragen , aber könntest Du Dich mit der Idee anfreunden im Header deiner UDF einen Modified-Eintrag zu machen, z.B. :
Habe meinen Post #3 editiert und im Header in der von mir geänderten UDF im Anhang vermerkt, was ich wo geändert habe.
Mit "... das Thema hatten wir vor kurzem" meinst Du wahrscheinlich : Zahlen größer 64-Bit , oder ?
Gruß Musashi
Hi,
da bin ich nochmal - hatte mich da leider zu früh gefreut ...
denn die Zahlen in meiner Funktion haben teilweise bis 20-Stellen.
die meisten Rechenaufgaben bekomme ich mit der Bignum.au3 hin.
Aber die Binary.au3 scheint diese nicht mehr zu unterstützen. z.B.
_BitXOR64(7169266485658129490,17399588354581095834) = 2054105551196646317 <> 10523109720805372360
Habt Ihr da noch eine Idee?
Oder haben wir den Rand des Universums bereits erreicht?
Habt Ihr da noch eine Idee?
Oder haben wir den Rand des Universums bereits erreicht?
Den Rand des Universums nicht, wohl aber die Darstellungsgrenze von Int64 .
Beide Deiner Werte sind größer als 9223372036854775807 (2^63 - 1), also dem Maximum von Int64 .
$iInt32 = 2147483647 ; 2^31 -1 = höchster Int32
$iInt64 = $iInt32 + 1 ; kleinster 64Int
ConsoleWrite("VarType = " & VarGetType($iInt32) & " Value = " & $iInt32 & @CRLF)
ConsoleWrite("VarType = " & VarGetType($iInt64) & " Value = " & $iInt64 & @CRLF)
$iInt64 = 9223372036854775807 ; 2^63 -1 = höchster Int64
ConsoleWrite("VarType = " & VarGetType($iInt64) & " Value = " & $iInt64 & @CRLF)
; Werte von @UPIA :
; _BitXOR64(9226309971060714224,17399588354581095866)
$iValue1 = 9226309971060714224
$iValue2 = 17399588354581095866
ConsoleWrite("UPIA : Value1 VarType = " & VarGetType($iValue1) & " Value = " & $iValue1 & @CRLF)
ConsoleWrite("UPIA : Value2 VarType = " & VarGetType($iValue2) & " Value = " & $iValue2 & @CRLF)
Alles anzeigen
Genau dafür wurde eigentlich die BigNum.au3 erstellt.
EDIT :
UPIA - siehe Beitrag von Ward zu seiner Binary.UDF :
https://www.autoitscript.com/forum/topic/131037-binary-udf/
Auszug :
These functions are just the same as built-in function in the same name but these can handle 64 bit signed integer :
_BitShift64($Value, $Shift)
_BitRotate64($Value, $Shift)
_BitNOT64($Value)
_BitOR64($Value1, $Value2, [$Value3, ...])
_BitAND64($Value1, $Value2, [$Value3, ...])
_BitXOR64($Value1, $Value2, [$Value3, ...])
_Hex64($Value, $Length = 16)
_Dec64($HexString)
Die Kernaussage hier lautet : "... these can handle 64 bit signed integer"
Daher ist der höchste (positive) Wert für Int64 (2^63 -1) = 9223372036854775807, da ein Bit für das Vorzeichen verwendet wird.
(EDIT Ende)
Gruß Musashi
ja aber natürlich sprach ich vom Zahlenuniversum
Für Multiplikation, Division, etc ist die Bignum.au3 ja super (hatte die auch schon im Einsatz),
aber da ist ja keine BitXOR drin (oder hab ich was übersehen?).
und die _BitXOR64 wirft mir bei sehr großen Zahlen (> 64bit) ein anderes Ergebnis aus als C++ (das hatte ich beim Schnelltesten der Binary.au3 übersehen)
sry, hatte mich da nicht klar ausgedrückt ..
... die _BitXOR64 wirft mir bei sehr großen Zahlen (> 64bit) ein anderes Ergebnis aus als C++ (das hatte ich beim Schnelltesten der Binary.au3 übersehen)
Der Grund ist, dass die Binary.UDF mit 64 Bit Signed-Integern arbeitet. Da ich dafür keinen neuen Beitrag schreiben wollte, habe ich das im Beitrag #10 hinzugefügt - hast Du ggf. nicht mitbekommen .
Für Multiplikation, Division, etc ist die Bignum.au3 ja super (hatte die auch schon im Einsatz),
aber da ist ja keine BitXOR drin (oder hab ich was übersehen ?).
Da ich bisher nicht mit der BigNum.UDF gearbeitet habe, kann ich dazu nichts sagen. Es ist aber sicher möglich, dass man dbzgl. eine entsprechende Erweiterung schreiben kann.
Gruß Musashi
Naja,
das ist für einen Programmieranfänger doch nur eine Fleißaufgabe.
Eine beliebig große Anzahl "Ziffern" ins entsprechende Binärformat bzw Hex umwandeln, und "blockweise" 64Bit wie gehabt XORen. Imho hatten wir das unlängst sogar hier im Forum.
Suche (schnelle) Funktion zum Umrechnen ins Dual- oder Hexadezimalsystem
hups...."unlängst"....5 Jahre her, aber trotz meines biblischen Alters habe ich mich noch dran erinnert^^
Link zum Post mit einem letztendlich schnellen Script: Suche (schnelle) Funktion zum Umrechnen ins Dual- oder Hexadezimalsystem
okay, werde mir das am WE mal anschauen,
solange lasse ich den thread mal noch offen.
danke für die Antworten!!
Alles anzeigenNaja,
das ist für einen Programmieranfänger doch nur eine Fleißaufgabe.
Eine beliebig große Anzahl "Ziffern" ins entsprechende Binärformat bzw Hex umwandeln, und "blockweise" 64Bit wie gehabt XORen. Imho hatten wir das unlängst sogar hier im Forum.
Suche (schnelle) Funktion zum Umrechnen ins Dual- oder Hexadezimalsystem
hups...."unlängst"....5 Jahre her, aber trotz meines biblischen Alters habe ich mich noch dran erinnert^^Link zum Post mit einem letztendlich schnellen Script: Suche (schnelle) Funktion zum Umrechnen ins Dual- oder Hexadezimalsystem
Erfreulich zu sehen, dass das Gedächtnis bei jüngeren Leuten noch so gut funktioniert .
UPIA :
Der Hinweis von Andy (Skript von eukalyptus) ist - wie gewohnt - sehr hilfreich.
Die Umwandlung Dezimalstring <-> Binärstring ist schnell und 'idiotensicher'.
Für eine eigene XOR Funktion solltest Du kürzere Binärstrings linksseitig mit Nullen auffüllen (auf die Länge des 'längsten' Binärstrings). Ob Du die Verknüpfung dann blockweise machst oder Bit für Bit, ist Dir überlassen.
In Deinem Skript gab es (meiner Meinung nach) noch eine kleine Definitionslücke :
Besetzt man den Dezimalstring mit "0", dann liefert _BigNum_DecToBin() einen Leerstring zurück. Dezimal="0" soll aber sicher auch Binär="0" ergeben. Ich habe einen simplen Fix eingebaut.
; Author : @eukalyptus
; 24. Januar 2014
; Link : https://autoit.de/index.php?thread/28809-suche-schnelle-funktion-zum-umrechnen-ins-dual-oder-hexadezimalsystem/&postID=355460#post355460
;
; Modified by @Musashi (2019-03-15)
; _BigNum_DecToBin returns an empty Binarystring if Decimalstring = "0" *** fixed
$sDec = "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"
$iTimer = TimerInit()
$sBin = _BigNum_DecToBin($sDec)
ConsoleWrite("> Time Decimal To Binary : " & StringFormat("%.2f", TimerDiff($iTimer)) & @CRLF)
$iTimer = TimerInit()
$sDec2 = _BigNum_BinToDec($sBin)
ConsoleWrite("> Time Binary To Decimal : " & StringFormat("%.2f", TimerDiff($iTimer)) & @CRLF)
If $sDec2 = $sDec Then
ConsoleWrite("+ Richtig : " & @CRLF & "+ $sDec : " & $sDec & @CRLF & "+ $sDec2 : " & $sDec2 & @CRLF & "+ $sBin : " & $sBin & @CRLF & @CRLF)
Else
ConsoleWrite("+ Falsch : " & @CRLF & "+ $sDec : " & $sDec & @CRLF & "+ $sDec2 : " & $sDec2 & @CRLF & "+ $sBin : " & $sBin & @CRLF & @CRLF)
_Compare($sDec, $sDec2)
EndIf
Func _Compare($sX, $sY)
Local $aX = StringSplit($sX, "")
Local $aY = StringSplit($sY, "")
ConsoleWrite("! ")
For $i = 1 To $aX[0]
If $aX[$i] = $aY[$i] Then
ConsoleWrite("_")
Else
ConsoleWrite("|")
ExitLoop
EndIf
Next
ConsoleWrite(@CRLF)
EndFunc ;==>_Compare
Func _BigNum_DecToBin($sDec)
Local $tChr = DllStructCreate("char[65];")
Local $sRet = ""
If ($sDec == "0") Then Return("0") ; *** added by @Musashi
While Not ($sDec = "0")
DllCall("msvcrt.dll", "ptr:cdecl", "_i64toa", "int64", __BigNum_DecToBinDiv($sDec), "struct*", $tChr, "int", 2)
$sRet = StringRight("0000000000000000000000000000000000000000000" & DllStructGetData($tChr, 1), 43) & $sRet
WEnd
Return StringRegExpReplace($sRet, "^0+([^0]|0$)", "\1", 1)
EndFunc ;==>_BigNum_DecToBin
Func _BigNum_BinToDec($sBin)
Local Const $cPOT = 32
Local Const $cDVS = Int(2 ^ $cPOT)
Local $aBin = StringRegExp($sBin, '\A.{' & $cPOT - (Ceiling(StringLen($sBin) / $cPOT) * $cPOT - StringLen($sBin)) & '}|.{' & $cPOT & '}+', 3)
Local $aResult, $sTmp, $sPot = "1", $sDec = "0"
For $i = UBound($aBin) - 1 To 0 Step -1
$sTmp = $sPot
$aResult = DllCall("msvcrt.dll", "uint64:cdecl", "_strtoui64", "str", $aBin[$i], "ptr", 0, "int", 2)
__BigNum_BinToDecMul($sTmp, $aResult[0])
__BigNum_BinToDecAdd($sDec, $sTmp)
__BigNum_BinToDecMul($sPot, $cDVS)
Next
Return StringRegExpReplace($sDec, "^0+([^0]|0$)", "\1", 1)
EndFunc ;==>_BigNum_BinToDec
Func __BigNum_BinToDecAdd(ByRef $sX, $sY)
Local $iTmp = StringLen($sX), $iLen = StringLen($sY), $iCar = 0, $sRet = ""
If $iLen < $iTmp Then $iLen = $iTmp
For $i = 1 To $iLen Step 18
$iTmp = Int(StringRight($sX, 18)) + Int(StringRight($sY, 18)) + $iCar
$sX = StringTrimRight($sX, 18)
$sY = StringTrimRight($sY, 18)
If ($iTmp > 999999999999999999) Then
$iTmp = StringRight($iTmp, 18)
$sRet = $iTmp & $sRet
$iCar = 1
Else
$iTmp = StringRight("000000000000000000" & $iTmp, 18)
$sRet = $iTmp & $sRet
$iCar = 0
EndIf
Next
$sX = StringRegExpReplace($iCar & $sRet, "^0+([^0]|0$)", "\1", 1)
EndFunc ;==>__BigNum_BinToDecAdd
Func __BigNum_BinToDecMul(ByRef $sX, $iY)
Local $aX = StringRegExp($sX, '\A.{' & 6 - (Ceiling(StringLen($sX) / 6) * 6 - StringLen($sX)) & '}|.{6}+', 3)
For $i = 0 To UBound($aX) - 1
$aX[$i] = Int($aX[$i]) * $iY
Next
Local $iCar = 0, $iTmp
$sX = ""
For $i = UBound($aX) - 1 To 0 Step -1
$aX[$i] += $iCar
$iCar = Floor($aX[$i] / 1000000)
$iTmp = Mod($aX[$i], 1000000)
If $iTmp <= 1000000 Then $iTmp = StringRight("000000" & $iTmp, 6)
$sX = $iTmp & $sX
Next
If $iCar > 0 Then $sX = $iCar & $sX
$sX = StringRegExpReplace($sX, "^0+([^0]|0$)", "\1", 1)
EndFunc ;==>__BigNum_BinToDecMul
Func __BigNum_DecToBinDiv(ByRef $sX)
Local Const $cDVS = 8796093022208
Local $sRet = "", $iRem = StringLeft($sX, 15), $iTmp = 0, $iTrm = 6, $iLen
$sX = StringTrimLeft($sX, 15)
$iTmp = Floor($iRem / $cDVS)
$sRet &= $iTmp
$iRem -= $iTmp * $cDVS
While StringLen($sX) > 0
$iTrm = 15 - StringLen($iRem)
$iTmp = StringLeft($sX, $iTrm)
$iLen = StringLen($iTmp)
$iRem &= $iTmp
$sX = StringTrimLeft($sX, $iTrm)
$iTmp = Floor($iRem / $cDVS)
$iTmp = StringRight("000000000000000" & $iTmp, $iLen)
$sRet &= $iTmp
$iRem -= $iTmp * $cDVS
WEnd
$sX = StringRegExpReplace($sRet, "^0+([^0]|0$)", "\1", 1)
Return $iRem
EndFunc ;==>__BigNum_DecToBinDiv
Alles anzeigen
Gruß Musashi
Erfreulich zu sehen, dass das Gedächtnis bei jüngeren Leuten noch so gut funktioniert
Hehe :o), werd du erst mal so alt, wie ich aussehe
Für eine eigene XOR Funktion solltest Du kürzere Binärstrings linksseitig mit Nullen auffüllen (auf die Länge des 'längsten' Binärstrings). Ob Du die Verknüpfung dann blockweise machst oder Bit für Bit, ist Dir überlassen.
Da das hier ja ein Programmier(er)forum ist, sollte der geneigte "User" eine Funktion erstellen und diese dann hier posten, so dass man sie in die BigNum.UDF übernehmen kann.
Wie gesagt, eine "kleinere" Programmierübung. Das sollte auch ein Anfänger schaffen.
Habe die in Post #3 von mir geänderte Binary.au3 nochmals ein wenig umgeändert.
; 3. Change the Code in _BinaryAnd, _BinaryOR, _BinaryXOR, _BinaryNot,
; _BinaryShift, _BinaryRotate, _BinaryReverse, _BinaryInBin, _BinaryReplace,
; _BinaryRandom
; From:
; Static $CodeBufferPtr
; If Not $CodeBufferPtr Then
; Local $Code
; If @AutoItX64 Then
; $Code = Binary("0x...")
; Else
; $Code = Binary("0x...")
; EndIf
; $CodeBufferPtr = __BinaryCodeBufferAlloc($Code)
; EndIf
; To:
; Local Static $aCode = ["0x...(X86)", "0x...(X64)"], _
; $CodeBufferPtr = __BinaryCodeBufferAlloc($aCode[@AutoItX64])
Alles anzeigen
Und weil es zum Thema passt, findet ihr hier im Anhang noch eine kleine UDF von mir...
Funktionen: _BinaryMidAND, _BinaryMidNOT, _BinaryMidOR, _BinaryMidXOR