Tukar Endianness


20

Seperti yang mungkin Anda ketahui, memori perangkat keras (byte-addressable) dapat dibagi menjadi dua kategori - little-endian dan big-endian . Dalam ingatan little-endian byte-byte diberi nomor dimulai dengan 0 pada akhir yang sedikit (paling tidak signifikan) dan pada yang big-endian sebaliknya.

Fakta menyenangkan : Istilah-istilah ini didasarkan pada buku Jonathan Swift , Gulliver's Travels di mana raja Lilliputian memerintahkan warganya untuk memecahkan telur mereka di ujung kecil (dengan demikian si kecil-endian) dan para pemberontak akan memecahkannya di ujung besar.

Bagaimana swapping bekerja

Misalkan kita memiliki integer unsigned (32bit) 12648430dalam memori, dalam mesin big-endian yang mungkin terlihat sebagai berikut:

  addr: 0  1  2  3
memory: 00 C0 FF EE

Dengan membalik urutan byte kita mendapatkan integer heksadesimal 0xEEFFC000yang 4009738240dalam desimal.

Tugas Anda

Tulis program / fungsi yang menerima bilangan bulat 32-bit yang tidak ditandatangani dalam desimal dan mengeluarkan bilangan bulat yang dihasilkan ketika menukar endianness seperti dijelaskan di atas.

Aturan

  • Input akan selalu dalam kisaran 0hingga4294967295
  • Output dapat dicetak ke STDOUT (mengikuti baris / spasi baik-baik saja) atau dikembalikan
  • Input dan output dalam desimal
  • Perilaku pada input yang tidak valid dibiarkan tidak terdefinisi

Uji kasus

0 -> 0
1 -> 16777216
42 -> 704643072
128 -> 2147483648
12648430 -> 4009738240
16885952 -> 3232235777
704643072 -> 42
3735928559 -> 4022250974
4009738240 -> 12648430
4026531839 -> 4294967279
4294967295 -> 4294967295

Untuk jawaban fungsi, apakah "input dan output dalam desimal" berarti string karakter digit atau array nilai digit diperlukan? Atau dapatkah suatu fungsi menjawab menggunakan representasi nilai integer alami bahasanya, yang dalam kebanyakan kasus sama sekali tidak ada hubungannya dengan "desimal"?
aschepler

1
@aschepler Nilai integer bahasa, mis. 42diberikan dalam desimal tetapi secara teknis itu dalam biner dalam C misalnya. Anda tentu saja dapat mengetik 0x2a, apa yang ingin saya cegah adalah mengambil input sebagai string suka "2a"atau sejenisnya.
ბიმო

Terkait (karena tantangan ini hanya memastikan untuk
memasukkan

Jawaban:


25

bahasa mesin x86_32, 3 byte

endian_swap:        # to be called with PASCAL REGISTER calling convention
0f c8    bswap eax
c3       ret

Ini sedikit curang. Konvensi panggilan register Pascal (lihat Wikipedia ) sedikit mirip dengan __fastcall, kecuali ia melewati parameter pertama dalam eax, dan eax juga mengandung nilai balik. Ini juga pembersihan-callee, tetapi karena kita tidak menggunakan stack untuk apa pun selain pointer kembali kita tidak perlu melakukan apa-apa. Ini memungkinkan kita untuk menghindari mov atau xchg dan cukup menggunakan bswap secara langsung.


Mungkin ingin diperhatikan yang bswapmembutuhkan 80486 atau lebih tinggi :)
ceilingcat

@ceilingcat Sangat benar, walaupun saya yakin itu secara implisit terjadi pada banyak solusi lain di sini karena pembatasan kompilator atau toolchain!
Polinomial

10

x86_64 bahasa mesin Linux, 5 4 byte

0:       0f cf                   bswap  %edi
2:       97                      xchg   %eax,%edi
3:       c3                      retq 

Terima kasih kepada @peter ferrie untuk -1.

Cobalah online!


itu bukan nilai balik desimal. Saya tidak berpikir itu penting. Selain itu, Anda bisa xchg edi, eax selama 4 byte.
peter ferrie

@peterferrie Wow, saya baru saja meramban situs web Anda membaca tentang header PE!
ceilingcat


6

Japt , 10 14 byte

sG ùT8 ò w ¬nG

Cobalah


Penjelasan

Konversi integer input ke string basis-16 ( sG), gunakan 0untuk mengisi awal hingga panjang 8 ( ùT8), pisah menjadi array 2 string karakter ( ò), mundur ( w), bergabung kembali ke string ( ¬) dan mengkonversi kembali ke basis- 10 ( nG).


Anda tahu, apa yang mungkin merupakan fitur praktis adalah memiliki lebih banyak fungsi seperti yitu, ketika diberi fungsi fungsi, menerapkan transformasi normal mereka, menjalankan fungsi, dan kemudian membalikkan transformasi. Dalam hal ini saya pikir itu akan mempersingkat menjadi sG_ò w ¬8 byte. Atau jika òmelakukannya juga, bisa jadi sG_ò2_wuntuk 7 ...
ETHproduksi

@ ETHproductions Saya mendukungnya; yang bawah- &.keterangan di J melakukan ini dan itu kadang-kadang benar-benar membantu dalam golf. Pengodean dalam semua inversi mungkin membosankan.
cole

@ ETHproductions: semakin "kelebihan", semakin baik :) Saya menulis ini sambil menarik gelas dan awalnya sG_òw..., tidak bisa, untuk kehidupan saya, mencari tahu mengapa itu tidak berhasil! Saya akhirnya menyadari kesalahan saya!
Shaggy

Tampaknya tidak berfungsi untuk input yang kurang dari 2 << 24 ...
Neil

Terima kasih, @Neil; akan memperbaikinya nanti. Sepertinya akan dikenakan biaya 4 byte.
Shaggy



5

APL + MENANG 14 byte

256⊥⌽(4⍴256)⊤⎕

Penjelasan

⎕ prompt for screen input
(4⍴256)⊤ 4 byte representation in base 256
⌽ reverse bytes
256⊥ bytes from base 256 to integer

1
Akan 256⊥⌽⎕⊤⍨4⍴256bekerja untuk -1 byte?
Erik the Outgolfer

Operator ⍨ tidak tersedia di APL + WIN sehingga jawabannya tidak tetapi mungkin ya untuk Dyalog APL
Graham

5

C # , 70 68 byte

Ini mungkin tidak optimal.

68:

Func<uint,uint>f=n=>((n=n>>16|n<<16)&0xFF00FF00)>>8|(n&0xFF00FF)<<8;

70:

uint e(uint n){n=n>>16|n<<16;return(n&0xFF00FF00)>>8|(n&0xFF00FF)<<8;}

Cobalah online!


Anda dapat memindahkan tugas ke returnekspresi dan kemudian menggunakan sintaks anggota bertubuh ekspresi: uint e(uint n)=>((n=n>>16|n<<16)&0xFF00FF00)>>8|(n&0xFF00FF)<<8;untuk 64 byte.
hvd

@ Hvd Itu tidak menunjukkan sintaks bertubuh ekspresi yang valid untuk saya. Namun saya bisa menggunakan trik pengaturan ulang shift untuk mencukur 2 byte.
Polinomial

Saya menyalin dan menempelkan dari komentar saya ke tautan TIO Anda untuk memastikan tidak ada kesalahan ketik atau apa pun seperti itu dan persis seperti yang ada di komentar saya, ia berfungsi: TIO tautan
hvd

Saya perhatikan 0xFF00FF00 adalah pelengkap 0xFF00FF dan bertanya-tanya apakah Anda dapat memanfaatkannya? Tetapi mendeklarasikannya sebagai variabel, membutuhkan terlalu banyak karakter
PrincePolka

Oh! Baik untuk memeriksa konstanta memang: Anda dapat menggunakan 0xFF00FFdua kali oleh >>ing sebelum &ing, dan Anda kemudian dapat mempersingkat 0xFF00FFke ~0u/257: uint e(uint n)=>((n=n>>16|n<<16)>>8&~0u/257)|(n&~0u/257)<<8;untuk 60. Link TIO
HVD


4

05AB1E , 12 10 byte

3F₁‰R`})₁β

Cobalah online! Penjelasan:

  ₁         Integer constant 256
   ‰        [Div, Mod]
    R       Reverse
     `      Flatten to stack
3F    }     Repeat 3 times
       )    Collect results
        ₁β  Convert from base 256

1
Ini sepertinya bukan solusi yang valid. "Padding" yang Anda lakukan sebenarnya mengulangi daftar byte hingga panjang 4.
Erik the Outgolfer

@EriktheOutgolfer Bah, saya berharap dokumentasi akan benar-benar mengatakan bahwa ...
Neil

3

JavaScript (ES6), 45 43 byte

f=(n,p=0,t=4)=>t?f(n>>>8,p*256+n%256,t-1):p

1
Dimulai dengan t=0menghemat 2 byte:f=(n,p=t=0)=>t++<4?f(n>>>8,p*256+n%256):p
Arnauld


3

MATL , 12 10 byte

7Y%1Z%P7Z%

Cobalah online! Atau verifikasi semua kasus uji .

Penjelasan

        % Implicitly input a number, read as a double
7Y%     % Cast to uint32
1Z%     % Convert to uint8 without changing underlying data. The result is 
        % an array of four uint8 numbers, each corresponding to a byte of
        % the original number's representation 
P       % Flip array
7Z%     % Convert back to uint32 without changing underlying data. The array
        % of four uint8 numbers is interpreted as one uint32 number.
        % Implicitly display

2

JavaScript (ES6), 51 45 byte

Disimpan 6 byte dengan bantuan @ Neil

n=>(n>>>24|n>>8&65280|(n&65280)<<8|n<<24)>>>0

Uji kasus


Bagus, terbaik yang bisa saya dapatkan dengan rekursi adalah f=(n,p=0,t=4)=>t?f(n/256|0,p*256+n%256,t-1):p.
ETHproduksi

@ ETHproductions ... itu lebih pendek?
Erik the Outgolfer

1
@ ETHproductions Itu pasti lebih pendek. Anda harus mempostingnya.
Arnauld

46 byte:n=>(n>>>24|n>>8&65280|n<<8&16711680|n<<24)>>>0
Neil

1
@ hvd Jangan khawatir. Anda dapat menambahkannya sebagai versi alternatif atau mengganti yang sudah ada seluruhnya. Terserah kamu!
Arnauld

2

J, 16 byte

|.&.((4#256)#:])

Cobalah online!

Berusaha memperpendek ekspresi kanan. Saya pikir saya bisa mencukur beberapa byte dengan membuat ini bekerja dengan versi beta J. Saya bersumpah saya melihat di sini bahwa Anda dapat mengakhiri kereta dengan kata benda dalam versi beta baru ...

Penjelasan

|.&.((4#256)#:])
    ((4#256)#:])  Convert to 4 two-byte blocks
            #:      Debase to
      4#256         4 digits base 256
  &.              Apply right function, left function, then inverse of right
|.                Reverse digits

Konversi ke basis 4 digit 256, balikkan digit, lalu konversikan kembali ke desimal. Pada dasarnya, lakukan algoritma yang disediakan di OP. Ini mungkin satu kali di mana itu membantu bahwa konversi basis campuran J mengharuskan Anda untuk menentukan jumlah digit, meskipun itu akan menjadi 2 byte lebih sedikit jika saya bisa mengakhiri kereta dalam kata benda ( (#:~4#256)sebagai gantinya).


2

Excel VBA, 103 92 Bytes

Fungsi jendela langsung VBE anonim yang mengambil input dari rentang [A1]dikonversi ke hex, membalikkan byte, dan output ke jendela langsung VBE

h=[Right(Rept(0,8)&Dec2Hex(A1),8)]:For i=0To 3:s=s+Mid(h,7-2*i,2):Next:[B1]=s:?[Hex2Dec(B1)]

Bisakah saya menguji ini di suatu tempat? Bisakah Anda menambahkan penerjemah online?
ბიმო

2
@BruceForte Tidak, sayangnya tidak ada juru bahasa online untuk varian VBA, namun, jika Anda memiliki salinan Excel di komputer Anda, Anda dapat mengakses VBE dengan menekan Alt + F11, dan kemudian jendela langsung dengan menekan Ctrl + G. Untuk fungsi anonim ini, Anda kemudian akan menempelkan input Anda ke sel A1 dan kode di atas ke jendela langsung dan tekan enter
Taylor Scott

Oh - dan kadang-kadang VBA agak funky (dan versi Mac secara imperial lebih buruk daripada versi windows) jadi ini, dan kecuali dinyatakan sebaliknya, solusi VBA mengasumsikan versi Windows 32-Bit default
Taylor Scott

2

Majelis PPC (32-bit), 8 byte

endian_swap:    # WORD endian_swap(WORD)
7c 60 1c 2c     LWBRX 3,0,3
4e 80 00 20     BLR

Bagaimana ini bekerja:

  • Konvensi panggilan PPC menempatkan parameter kata 32-bit pertama ke SP + 24, dan membayangi alamat itu ke GPR3.
  • LWBRX mengambil beban GPR3 ​​(operan ketiga) dan nol- meluasnya (operan kedua) ke EA, kemudian membaca 4 byte dalam urutan terbalik dan menyimpannya dalam GPR3 ​​(operan pertama).
  • GPR3 memegang nilai pengembalian.
  • BLR kembali dari fungsi (cabang ke alamat di register LR)

Sayangnya tidak ada emulator perakitan PPC online yang bisa saya temukan untuk didemonstrasikan. Maaf!


2

Befunge, 62 61 atau 49 byte

0&0v!p22:/3g22/*:*82\+%*:*82+<
@.$_:28*:*%00p\28*:**00g28*:*^

Cobalah online!

Ini menggunakan Befunge standar pada interpreter referensi, dan karenanya kita perlu memperhitungkan fakta bahwa sel-sel memori bertanda 8-bit, dan mengoreksi kemungkinan overflow yang ditandatangani.

Pada implementasi dengan sel-sel memori yang tidak ditandatangani (misalnya PyFunge), atau di mana kisaran lebih besar dari 8 bit (misalnya FBBI), kita dapat pergi tanpa pemeriksaan itu, menghemat 12 byte.

0&0v!p22:/3g22/*:*82\+g<
@.$_:28*:*%00p\28*:**00^

Coba FBBI online!
Coba PyFunge online!

Meskipun perhatikan bahwa PyFunge memiliki input integer pemrosesan bug, jadi saat menguji pada TIO Anda harus mengikuti angka di bidang input dengan spasi atau jeda baris.


2

Oktaf , 10 byte

@swapbytes

Cobalah online!

Ini mungkin pertama kalinya Octave memiliki skor yang sama persis dengan turunan golfnya, MATL. Tentu saja, dalam hal ini, Octave-lah yang memiliki built-in, bukan MATL, membuatnya jauh lebih mudah.

Menentukan pegangan ke built-in swapbytes, yang mengambil tipe data apa pun, menukar endianness dan mengeluarkan hasilnya. Dalam hal ini, inputnya adalah integer unsigned 32-bit.



2

R , 86 byte

Saya pikir sudah ada jawaban (atau dua) dalam R untuk pertanyaan ini, tetapi saya pasti salah atau mereka memiliki masalah yang sama dengan R yang tidak menandatangani int. Masalah itu mengeluarkan semua bawaan yang bisa membantu. Saya mencoba konversi 256 basis, tetapi akhirnya terlalu lama, tapi saya pikir masih ada ruang bagi seseorang yang lebih pintar daripada saya untuk melakukan itu. Lalu saya berakhir dengan yang berikut ini yang konversi basis 2 bertukar urutan dalam fungsi rekursif.

f=function(x,y=0,i=31)'if'(i+1,f(x-(2^i*z),y+(2^((3-i%/%8)*8+i%%8)*(z=2^i<=x)),i-1),y)

Cobalah online!

f=function(x,y=0,i=31)       # set up the function and initial values
  'if'(i+1,                  # test for i >= 0
    f(                       # recursively call the function
      x-(2^i*z),             # remove 2^i from x when 2^i <= x
      y+(2^                  # add to y 2 to the power of
        ((3-i%/%8)*8+i%%8)   # calc to swap the order of the bytes
        *(z=2^i<=x)),        # when 2^i <= x
      i-1),                  # decrement i
   y)                        # return y

Anda benar tentang basis 256 yang lebih pendek!
Giuseppe

@ Giuseppe, Anda akan memasang topi, bukan
MickyT

2

R , 41 byte

function(n)n%/%256^(0:3)%%256%*%256^(3:0)

Cobalah online!

Verifikasi semua kasus uji!

Menggunakan konversi basis-256 seperti yang disarankan MickyT di sini . R tidak memiliki bilangan bulat 32-bit yang tidak ditandatangani, juga tidak memiliki bilangan bulat 64-bit. Ini mencegah kita dari menggunakan operasi bitwise tetapi pendekatan ini (dan kemungkinan MickyT) mungkin masih lebih pendek karena operator bitwise R cukup bertele-tele.

Gunakan nomor 4 tip ini , dengan mempertimbangkan bahwa kami tidak pernah mendapatkan angka sebesar ini 256^4.

n%/%256^(0:3)%%256mengekstrak byte, dan %*%, produk matriks, adalah produk titik dalam situasi ini, dengan 256^(3:0)memengaruhi urutan byte yang dibalik. %*%akan mengembalikan 1x1 yang matrixberisi nilai endian-reversed.


1

Perakitan CP-1610 , 6 DECLEs = 8 byte

Kode ini dimaksudkan untuk dijalankan pada Intellivision .

Sebuah opcode CP-1610 dikodekan dengan nilai 10-bit, yang dikenal sebagai 'DECLE'. Fungsi ini panjangnya 6 DECLEs, mulai dari $ 480C dan berakhir pada $ 4811.

CP-1610 memiliki register 16-bit, jadi kami menggunakan dua dari mereka (R0 dan R1) untuk menyimpan nilai 32-bit.

                               ROMW  10           ; use 10-bit ROM

                               ORG   $4800        ; start program at address $4800

                               ;; example call
4800  0001                     SDBD               ; load 0xDEAD into R0
4801  02B8 00AD 00DE           MVII  #$DEAD, R0
4804  0001                     SDBD               ; load 0xBEEF into R1
4805  02B9 00EF 00BE           MVII  #$BEEF, R1

4808  0004 0148 000C           CALL  swap32       ; call our function

480B  0017                     DECR  PC           ; loop forever

                               ;; swap32 function
                       swap32  PROC

480C  0040                     SWAP  R0           ; 16-bit SWAP of R0
480D  0041                     SWAP  R1           ; 16-bit SWAP of R1

480E  01C1                     XORR  R0, R1       ; exchange R0 and R1
480F  01C8                     XORR  R1, R0       ; using 3 consecutive eXclusive OR
4810  01C1                     XORR  R0, R1

4811  00AF                     JR    R5           ; return

                               ENDP

Tempat pembuangan eksekusi

 R0   R1   R2   R3   R4   R5   R6   R7    CPU flags  instruction
 ------------------------------------------------------------------
 0000 4800 0000 0000 01FE 1041 02F1 4800  ------iq   SDBD
 0000 4800 0000 0000 01FE 1041 02F1 4801  -----D-q   MVII #$DEAD,R0
 DEAD 4800 0000 0000 01FE 1041 02F1 4804  ------iq   SDBD
 DEAD 4800 0000 0000 01FE 1041 02F1 4805  -----D-q   MVII #$BEEF,R1
[DEAD BEEF]0000 0000 01FE 1041 02F1 4808  ------iq   JSR  R5,$480C

 DEAD BEEF 0000 0000 01FE 480B 02F1 480C  ------iq   SWAP R0
 ADDE BEEF 0000 0000 01FE 480B 02F1 480D  S------q   SWAP R1
 ADDE EFBE 0000 0000 01FE 480B 02F1 480E  S------q   XORR R0,R1
 ADDE 4260 0000 0000 01FE 480B 02F1 480F  ------iq   XORR R1,R0
 EFBE 4260 0000 0000 01FE 480B 02F1 4810  S-----iq   XORR R0,R1
[EFBE ADDE]0000 0000 01FE 480B 02F1 4811  S-----iq   MOVR R5,R7

 EFBE ADDE 0000 0000 01FE 480B 02F1 480B  ------iq   DECR R7

Mengapa 7,5 byte ini? Saya pikir itu harus 8 byte.
Erik the Outgolfer

@EriktheOutgolfer Cukup adil. Diperbarui sesuai.
Arnauld

@EriktheOutgolfer Karena 60 bit sama dengan 7,5 byte?
Jeppe Stig Nielsen

@ JeppeStigNielsen Itu benar, tetapi sebuah file tidak pernah bisa sepanjang 7,5 byte, itu akan menjadi pra atau pasca-empuk dengan 0s.
Erik the Outgolfer

@EriktheOutgolfer Secara teknis, ini benar - benar bisa - dapat disimpan dalam ROM 10-bit. Berikut adalah contoh lembar spesifikasi. (Hari ini, kami menggunakan ROM 16-bit untuk game homebrew Intellivision, tetapi pada hari itu, chip memori sangat mahal sehingga menggunakan 10-bit adalah penghemat uang nyata.)
Arnauld

1

C # (.NET Core) , 72 + 31 = 103 byte

m=>BitConverter.ToUInt32(BitConverter.GetBytes(m).Reverse().ToArray(),0)

Cobalah online!

+31 untuk using System;using System.Linq;

Saya berharap untuk menggunakan Array.Reverseinline, tetapi itu tidak terjadi (lihat alternatif di bawah).

C # (.NET Core) , 87 + 13 = 100 byte

m=>{var a=BitConverter.GetBytes(m);Array.Reverse(a);return BitConverter.ToUInt32(a,0);}

Cobalah online!

+13 untuk using System;

Solusi perawatan ini dari @JeppeStigNielsen; menghapus pembatasan memiliki semua yang sebaris disimpan 3 byte.


Karena Anda bisa menghemat using System.Linq;, masih bisa lebih murah untuk digunakan x=>{var a=BitConverter.GetBytes(x);Array.Reverse(a);return BitConverter.ToUInt32(a,0);}.
Jeppe Stig Nielsen

1

REXX , 42 byte

say c2d(left(reverse(d2c(arg(1))),4,'0'x))

Cobalah online!

Tidak Terkumpul:

n=arg(1) -- take n as argument
n=d2c(n) -- convert from decimal to character (bytes)
n=reverse(n) -- reverse characters
n=left(n,4,'0'x) -- extend to four bytes, padding with zeros
n=c2d(n) -- convert from bytes to decimal again
say n -- output result


1

Bahasa mesin ARM Linux, 8 byte

0:       e6bf0f30       rev     r0, r0
4:       e12fff1e       bx      lr

Untuk mencoba ini sendiri, kompilasi dan jalankan yang berikut di Raspberry Pi atau perangkat Android yang menjalankan GNUroot

#include<stdio.h>
#define f(x) ((unsigned int(*)(unsigned int))"0\xf\xbf\xe6\x1e\xff/\xe1")(x)
int main(){
  printf( "%u %u\n", 0, f(0) );
  printf( "%u %u\n", 1, f(1) );
  printf( "%u %u\n", 42, f(42) );
  printf( "%u %u\n", 128, f(128) );
  printf( "%u %u\n", 16885952, f(16885952) );
  printf( "%u %u\n", 704643072, f(704643072) );
  printf( "%u %u\n", 3735928559U, f(3735928559U) );
  printf( "%u %u\n", 4009738240U, f(4009738240U) );
  printf( "%u %u\n", 4026531839U, f(4026531839U) );
  printf( "%u %u\n", 4294967295U, f(4294967295U) );
}



1

K4 , 18 byte

Larutan:

0b/:,/8#|12 8#0b\:

Contoh:

q)\
  0b/:,/8#|12 8#0b\:0
0
  0b/:,/8#|12 8#0b\:1
16777216
  0b/:,/8#|12 8#0b\:42
704643072
  0b/:,/8#|12 8#0b\:4294967295
4294967295
  0b/:,/8#|12 8#0b\:4026531839
4294967279

Penjelasan:

Tidak ada int unsigned, jadi butuh input sebagai panjang.

Konversi menjadi boolean array (64bits), membentuk kembali, membalikkan, mengambil 8 byte pertama, mengkonversi kembali menjadi panjang.

0b/:,/8#|12 8#0b\: / the solution
              0b\: / convert to bits
         12 8#     / reshape into 12x8 grid (wraps)
        |          / reverse
      8#           / take first 8
    ,/             / flatten
0b/:               / convert to long

Bonus:

Versi 19 byte dalam OK yang dapat Anda Coba online!

2/,/8#|12 8#(64#2)\
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.