Autor | Zpráva | ||
---|---|---|---|
SeparateSK Profil |
Dobrý deň, pokúšam sa vytvoriť svoj vlastný formát čísel, ktoré by boli viac ako 1024-bitové, a skúšam vytvoriť bitové posuny.
Nuž funguje to iba vtedy, ak je číslo o ktoré sa majú bity posunúť menšie alebo sa rovná 8 a je deliteľné 4. <?php function bright(array $nums, $c){ $now=0; $v=0; $o=0; $a=0; for($i=0;$i<count($nums);$i++){ $v=$nums[$i]; $o=$v>>$c; $now=($o|$a); $a=($v<<$c); $nums[$i]=$now; } return $nums; } function toNum(array $nums){ $r=0; for($i=0;$i<=3;$i++){ $r=$r|($nums[$i]); if($i!=3) $r=$r<<8; } return $r; } $arr=array(0,0,255,255); $nArr4=bright($arr,4); $nArr7=bright($arr,7); $nArr12=bright($arr,12); echo "4: ".toNum($nArr4)." vs ".(0xffff>>4).PHP_EOL; //toto funguje echo "7: ".toNum($nArr7)." vs ".(0xffff>>7).PHP_EOL; //toto uz nie echo "12: ".toNum($nArr12)." vs ".(0xffff>>12).PHP_EOL; //a ani toto ?> Vedel by niekto pomôcť? Prosím, bez komentárov ako: "Načo znovu vymýšľať koleso, keď také niečo ako +1024 bitový formát ukladania čísel už určite existuje?" |
||
SeparateSK Profil |
Záhada s číslom 7 vyriešená:
$a=($v<<$c); bolo nahradené s $a=($v-$o); Ale bitshift s číslom 12 ešte stále nefunguje Výsvetlivky: $now - číslo, ktoré sa vloží späť do array (vznikne bitovým "or" čísla $v a zvyšku po minulom bitovom posune) $v - číslo, ktoré sa má upraviť $o - $v posunuté o $c bitov $a - zvyšok po bitovom posune , teda 10011>>2 = 100|11 - | je akoby hranica |
||
Jan Tvrdík Profil |
SeparateSK:
Neměla by funkce bright vyhazovat ty pravé bity?
Viděl bych to asi takto: <?php function bright(array $nums, $c) { $byteShift = (int) ($c / 8); for ($i = count($nums) - 1; $i >= 0; $i--) { $nums[$i] = isset($nums[$i - $byteShift]) ? $nums[$i - $byteShift] : 0; } $c %= 8; $mask = 255 >> (8 - $c); $remaining = 0; foreach ($nums as $i => $num) { $nums[$i] = ($num >> $c) | $remaining; $remaining = ($num & $mask) << (8 - $c); } return $nums; } function toNum(array $nums) { $result = 0; foreach ($nums as $num) { $result = ($result << 8) + $num; } return $result; } function dump($nums) { $nums = (array) $nums; foreach ($nums as $v) { printf('%08b ', $v); } printf("= %d\n", toNum($nums)); } $arr = array(0, 0, 255, 255); dump($arr); dump(bright($arr, 4)); dump(bright($arr, 7)); dump(bright($arr, 12)); Zahodil jsem to tvoje a napsal znovu, bylo to rychlejší než pochopit to tvoje. Nicméně funkce dump by ti mohla pomoc, pokud si s tím chceš i nadále hrát.
|
||
SeparateSK Profil |
#4 · Zasláno: 12. 3. 2013, 16:48:10
Má vraciať array, lebo keď prvý parameter bude array s 129 číslami, tak PHP nepodporuje 1025 bitové čísla.
|
||
DJ Miky Profil |
Nemůžeš každý prvek posouvat o víc jak 8 bitů doprava, když máš osmibitové prvky. Obecný algoritmus na bitový posun o
$posun bitů doprava (při osmibitových prvcích pole) by mohl vypadat nějak takto:
1) Za každých 8 bitů posunu se ti "ztratí" jeden (poslední) prvek pole, takže odstraníš celkem floor($posun / 8) prvků z konce pole. V případě, že chceš zachovat délku pole, tak na začátek pole přidáš stejný počet nulových prvků.
2) Tím vyřešíš posun o celé prvky pole a zbyde ti posunout celý výraz o $zbytek = $posun % 8 bitů doprava.
3) To se dá vyřešit cyklem od konce pole (od nejnižších bitů), kdy každý prvek posuneš o oněch $zbytek bitů doprava a zároveň k němu přičteš posledních $zbytek bitů z předchozího prvku posunutých o 8 - $zbytek bitů doleva. Tedy $pole[$i] = ($pole[$i] >> $zbytek) | ( ($pole[$i - 1] << (8 - $zbytek) ) % 256) samozřejmě s ošetřením, aby $pole[$i - 1] existovalo.
Takové řešení bude mj. mnohem rychlejší v případě posunů o čísla dělitelná osmi. |
||
SeparateSK Profil |
#6 · Zasláno: 12. 3. 2013, 16:50:12
Vďaka! Toto funguje skvele.
<?php function bright(array $nums, $c) { $byteShift = floor($c / 8); for ($i = count($nums) - 1; $i >= 0; $i--) { $nums[$i] = isset($nums[$i - $byteShift]) ? $nums[$i - $byteShift] : 0; } $c %= 8; $mask = 255 >> (8 - $c); $remaining = 0; foreach ($nums as $i => $num) { $nums[$i] = ($num >> $c) | $remaining; $remaining = ($num & $mask) << (8 - $c); } return $nums; } function toNum(array $nums) { $result = 0; foreach ($nums as $num) { $result = ($result << 8) + $num; } return $result; } function dump($nums) { $nums = (array) $nums; foreach ($nums as $v) { printf('%08b ', $v); } printf("= %d\n", toNum($nums)); } $arr = array(0, 0, 255, 255); dump($arr); dump(bright($arr, 4)); dump(bright($arr, 7)); dump(bright($arr, 12)); |
||
Časová prodleva: 11 let
|
0