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
?>
Ja potrebujem aby aj bright($arr,7) dalo správny výsledok a aj aby bright($arr,12) dalo správny výsledok.
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
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
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));

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: