Endianness'i değiştirin


20

Çoğunuzun bildiği gibi, (bayt adresli) donanım bellekleri iki kategoriye ayrılabilir - küçük endian ve big endian . Küçük endian anılarında baytlar, küçük (en az anlamlı) uçta 0 ile başlayarak ve diğer taraftan büyük endianlarda numaralandırılır.

Eğlenceli gerçek : Bu terimler Jonathan Swift'in Lilliputian kralının vatandaşlarına küçük ucunda yumurtalarını kırmalarını emrettiği Gulliver'in Seyahatleri kitabına dayanıyor (böylece küçük endians) ve isyancılar büyük uçlarını kırıyorlardı.

Takas nasıl çalışır?

12648430Aşağıdaki gibi görünebilecek büyük endian bir makinede bellekte işaretsiz bir tamsayı (32bit) olduğunu varsayalım :

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

Bayt sırasını ters çevirerek biz onaltılık tamsayı olsun 0xEEFFC000olduğunu 4009738240ondalık.

Senin görevin

Ondalık olarak işaretsiz bir 32bit tam sayı alan ve endianness'i yukarıda açıklandığı gibi değiştirirken ortaya çıkan tamsayıyı çıkaran bir program / fonksiyon yazın.

kurallar

  • Giriş her zaman şu aralıkta 0olacaktır:4294967295
  • Çıktı STDOUT'a yazdırılabilir (son satırlar / boşluklar iyi) veya döndürülebilir
  • Giriş ve çıkış ondalık
  • Geçersiz girişteki davranış tanımsız bırakıldı

Test senaryoları

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

Bir fonksiyon cevabı için, "girdi ve çıktı ondalıktır", bir basamak karakter dizisi veya basamak değer dizisi gerektiği anlamına mı geliyor? Ya da bir işlev cevabı kendi dilinin doğal ondalık sayı gösterimini kullanabilir, ki bu çoğu durumda "ondalık" ile hiçbir ilgisi yoktur?
aschepler

1
@aschepler Dilin tam sayı değeri, ör. 42ondalık olarak verilir, ancak teknik olarak örneğin C dilinde ikiliktir. Tabii ki yazabilirsiniz 0x2a, önlemek istedim girdi gibi bir dize "2a"veya benzeri almaktır .
ბიმო

Related (bu zorluk ilk önce 32 bit'e kadar
doldurmayı garantilediğinden

Yanıtlar:


25

x86_32 makine dili, 3 bayt

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

Bu biraz hile. Pascal kayıt çağırma kuralı ( Wikipedia'ya bakın ), ilk parametreyi eax'ta geçmesi dışında eax da dönüş değerini içerir. Ayrıca callee-cleanup, ancak yığını geri dönüş işaretçisinden başka bir şey için kullanmadığımızdan hiçbir şey yapmamız gerekmez. Bu, mov veya xchg'den kaçınmamızı ve doğrudan bswap'ı kullanmamızı sağlar.


Bunun bswap80486 veya daha yüksek bir
sürüm

@ceilingcat Çok doğru, ancak derleyici veya araç zinciri kısıtlamaları nedeniyle burada diğer birçok çözüm için örtük olarak eminim!
Polinom

10

x86_64 makine dili Linux, 5 4 bayt

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

-1 için @peter ferrie sayesinde .

Çevrimiçi deneyin!


bu ondalık bir dönüş değeri değildir. Bunun önemli olduğunu düşünmüyorum. Ayrıca, xchg edi, eax için 4 bayt.
peter ferrie

@peterferrie Vay canına sadece web sitenize göz atıyordum PE başlıkları hakkında okuma!
ceilingcat


6

Japt , 10 14 bayt

sG ùT8 ò w ¬nG

Dene


açıklama

Giriş tamsayısını bir base-16 dizesine dönüştürün ( sG), 0başlangıcını 8 ( ùT8) uzunluğuna getirmek için kullanın, 2 karakter dizisinden oluşan bir diziye bölünün ( ò), reverse ( w), bir dizeye ( ¬) yeniden katılın ve base- 10 ( nG).


Kullanışlı bir özellik ne olabilir, böyle ybir işleve işlev verildiğinde normal dönüşümlerini uygulayın, işlevi çalıştırın ve sonra dönüşümü tersine çevirin. Bu durumda, bunun sG_ò w ¬8 bayt için kısaltılmasına izin vereceğini düşünüyorum . Ya da eğer öyleyse ò, sG_ò2_w7 için bile olabilir ...
ETHproductions

@ETHproductions Bunu destekliyorum; J'deki yetersiz &.zarf bunu yapar ve bazen golf oynamada gerçekten yardımcı olur. Yine de tüm inversiyonlarda kodlama yapmak sıkıcı olabilir.
Cole

@ETHproductions: daha fazla "aşırı", daha iyi :) Ben pint çekerken yazdım ve başlangıçta sG_òw..., benim hayatım için neden işe yaramayacağını anlayamadım! Sonunda hatalarımı fark ettim!
Shaggy

2'den az girdi için çalışmıyor gibi görünüyor << 24 ...
Neil

Teşekkürler, @Neil; daha sonra düzeltilecek. Görünüşe göre bana 4 byte mal olacak.
Shaggy



5

APL + WIN 14 bayt

256⊥⌽(4⍴256)⊤⎕

açıklama

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

1
Misiniz 256⊥⌽⎕⊤⍨4⍴256-1 byte için çalışmak?
Outgolfer Erik

Cevap hayır ama iyi Dyalog APL için evet olabilir böylece ⍨ operatörü APL + WIN mevcut değildir
Graham

5

C # , 70 68 bayt

Bu muhtemelen uygun değildir.

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;}

Çevrimiçi deneyin!


Ödevi returnifadeye taşıyabilir ve sonra uint e(uint n)=>((n=n>>16|n<<16)&0xFF00FF00)>>8|(n&0xFF00FF)<<8;64 bayt için ifade gövdeli üye sözdizimini kullanabilirsiniz .
Hvd

@hvd Bu benim için geçerli bir ifade gövdeli sözdizimi olarak gösterilmiyor. Ancak 2 bayt tıraş etmek için vites yeniden düzenleme hilesini kullanabildim.
Polinom

Herhangi bir yazım hatası veya bunun gibi bir şey olmadığından emin olmak için yorumumdan TIO bağlantınıza kopyaladım ve yapıştırdım ve tam olarak benim yorumumda
hvd

0xFF00FF00 0xFF00FF'ın bir tamamlayıcısı olduğunu fark ettim ve bundan faydalanabilir misiniz? Ancak bir değişkenin bildirilmesi çok fazla karakter gerektirir
PrincePolka

Ah! Gerçekten sabitleri kontrol etmek iyi: ing önce ing 0xFF00FFiki kez kullanabilirsiniz ve daha sonra kısaltmak için : 60 için. TIO link>>&0xFF00FF~0u/257uint e(uint n)=>((n=n>>16|n<<16)>>8&~0u/257)|(n&~0u/257)<<8;
hvd


4

05AB1E , 12 10 bayt

3F₁‰R`})₁β

Çevrimiçi deneyin! Açıklama:

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

1
Bu geçerli bir çözüm gibi görünmüyor. Yaptığınız "dolgu" aslında bayt listesini 4'e
kadar tekrarlıyor

@EriktheOutgolfer Bah, keşke belgeler aslında şunu söyleseydi ...
Neil

3

JavaScript (ES6), 45 43 bayt

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

1
t=02 bayt ile başlıyor :f=(n,p=t=0)=>t++<4?f(n>>>8,p*256+n%256):p
Arnauld


3

MATL , 12 10 bayt

7Y%1Z%P7Z%

Çevrimiçi deneyin! Veya tüm test senaryolarını doğrulayın .

açıklama

        % 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 bayt

@ Neil's yardımı ile 6 bayt kaydedildi

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

Test senaryoları


Güzel, en iyi ben özyineleme ile alabilir oldu f=(n,p=0,t=4)=>t?f(n/256|0,p*256+n%256,t-1):p.
ETHproductions

@ETHproductions ... bu daha kısa mı?
Outgolfer Erik

1
@ETHproductions Bu kesinlikle daha kısa. Göndermelisiniz.
Arnauld

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

1
@hvd Endişelenme. Alternatif bir sürüm olarak ekleyebilir veya mevcut olanı tamamen değiştirebilirsiniz. Sana bağlı!
Arnauld

2

J, 16 bayt

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

Çevrimiçi deneyin!

Sağdaki ifadeyi kısaltmaya çalışmak. Sanırım bu işi beta J sürümü ile yaparak birkaç bayt tıraş edebilirim. Yemin ederim ki burada gördüm, yeni bir beta versiyonunda bir isimle bir treni bitirebilirsin ...

açıklama

|.&.((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

4 basamak taban 256'ya dönüştürün, basamakları ters çevirin, ardından ondalık basamağa geri dönüştürün. Temel olarak, OP'de sağlanan algoritmayı gerçekleştirin. Bu belki de J'nin karışık temel dönüşümünün basamak sayısını belirtmenizi gerektirdiği yararlı bir zamandır, ancak bir isimde treni bitirebilirsem 2 daha az bayt olurdu (#:~4#256).


2

Excel VBA, 103 92 Bayt

Aralıktan girdi alan anonim VBE anlık pencere işlevi [A1]onaltılık biçime dönüştürür, baytları tersine çevirir ve VBE anlık penceresine çıkışlar verir

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)]

Bunu bir yerde test edebilir miyim? Çevrimiçi bir tercüman ekleyebilir misiniz lütfen?
ბიმო

2
@BruceForte Hayır, ne yazık ki VBA'nın herhangi bir çeşidi için çevrimiçi tercüman yok, ancak bilgisayarınızda Excel'in bir kopyası varsa, Alt + F11 tuşlarına basarak VBE'ye ve ardından Ctrl tuşlarına basarak hemen pencereye erişebilirsiniz. + G. Bu anonim işlev için girişinizi A1 hücresine ve yukarıdaki kodu hemen pencereye yapıştırır ve enter tuşuna basarsınız
Taylor Scott

Oh - ve bazen VBA biraz korkak (ve Mac sürümü Windows sürümünden daha kötüdür) bu yüzden ve aksi belirtilmedikçe, VBA çözümleri varsayılan 32 Bit Windows sürümünü kabul eder
Taylor Scott

2

PPC Düzeneği (32 bit), 8 bayt

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

Bu nasıl çalışır:

  • PPC çağrı kuralı, ilk 32 bit sözcük parametresini SP + 24'e yerleştirir ve bu adresi GPR3'e gölgelendirir.
  • LWBRX yük GPR3'ü (üçüncü işlenen) alır ve sıfır (ikinci işlenen) EA'ya genişletir, sonra 4 baytı ters sırada okur ve GPR3'e (ilk işlenen) kaydeder.
  • GPR3 dönüş değerini tutar.
  • BLR işlevden döner (LR kaydındaki adrese dallar)

Ne yazık ki gösterebileceğim herhangi bir çevrimiçi PPC montaj emülatörü yok. Afedersiniz!


2

Befunge, 62 61 veya 49 bayt

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

Çevrimiçi deneyin!

Bu, referans yorumlayıcıda standart Befunge kullanıyor ve bu nedenle bellek hücrelerinin 8 bit imzalı olduğunu ve olası imzalı taşma için doğru olduğunu hesaba katmamız gerekiyor.

İmzasız bellek hücreleriyle (örn. PyFunge) veya aralığın 8 bitten (örn. FBBI) büyük olduğu uygulamalarda, bu kontroller olmadan kurtularak 12 bayt tasarruf edebiliriz.

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

FBBI'yı çevrimiçi deneyin!
PyFunge'u çevrimiçi deneyin!

PyFunge'nin bir hata işleme tamsayı girişine sahip olmasına rağmen, TIO üzerinde test yaparken, giriş alanındaki sayıyı boşluk veya satır sonu ile izlemeniz gerekir.


2

Oktav , 10 bayt

@swapbytes

Çevrimiçi deneyin!

Bu, Octave'nin golf türevi MATL ile tam olarak aynı puana sahip olması olabilir. Tabii ki, bu durumda, MATL yerine yerleşik olan Octave, çok daha kolay hale getiriyor.

swapbytesHerhangi bir veri türünü alan, endianlığı değiştiren ve sonucu çıktılayan yerleşik bir tanıtıcı tanımlar . Bu durumda, giriş 32 bit işaretsiz bir tam sayıdır.



2

R, , 86 bayt

Bu soru için R'de zaten bir cevap (ya da iki) olduğunu düşündüm, ancak yanılmış olmalıydım ya da R ile imzalanmış girişler yapmama ilişkin sorunlarım vardı. Bu sorun, yardımcı olabilecek herhangi bir yerleşimi ele geçirdi. 256 baz dönüşüm denedim, ama uzun sürdü, ama benden daha akıllı biri için hala yer var bence. Sonra bir özyinelemeli işlevi sırayla takas bir temel 2 dönüşüm aşağıdaki ile sona erdi.

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)

Çevrimiçi deneyin!

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

256 tabanının kısalması konusunda haklıydınız !
Giuseppe

@Giuseppe, sen bir şapka
takacaksın

2

R , 41 bayt

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

Çevrimiçi deneyin!

Tüm test senaryolarını doğrulayın!

MickyT'nin burada önerdiği gibi bir temel-256 dönüşümü kullanır . R'nin işaretsiz 32 bit tam sayıları veya 64 bit tam sayıları yoktur. Bu, bitsel işlemleri kullanmamızı engeller, ancak R'nin bitsel operatörleri oldukça ayrıntılı olduğundan bu yaklaşım (ve muhtemelen MickyT'ler) muhtemelen daha kısadır.

Asla bu kadar büyük bir sayı almadığımızı göz önünde bulundurarak bu ipucunun 4. sayısını kullanır 256^4.

n%/%256^(0:3)%%256baytları ayıklar ve %*%matris ürünü bu durumda nokta 256^(3:0)bayttır ve ters bayt sırasını etkiler. endian ters çevrilmiş değeri içeren %*%bir 1x1 döndürür matrix.


1

CP-1610 montajı, 6 DECLEs = 8 bayt

Bu kodun bir Intellivision üzerinde çalıştırılması amaçlanmıştır .

Bir CP-1610 op kodu, 'DECLE' olarak bilinen 10 bitlik bir değerle kodlanır. Bu işlev 6 DECLE uzunluğunda, 480C $ 'dan başlayıp 4811 $' dan bitiyor.

CP-1610'un 16 bitlik kayıtları vardır, bu nedenle 32 bitlik değeri depolamak için bunlardan ikisini (R0 ve R1) kullanıyoruz.

                               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

İcra dökümü

 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

Neden bu 7,5 bayt? Bence 8 bayt olmalı.
Outgolfer Erik

@EriktheOutgolfer Yeterince adil. Buna göre güncellendi.
Arnauld

@EriktheOutgolfer 60 bit 7,5 bayta eşit olduğundan?
Jeppe Stig Nielsen

@JeppeStigNielsen Bu doğru, ancak bir dosya asla 7,5 bayt uzunluğunda olamaz, 0'larla önceden veya sonra dolgulu olur.
Outgolfer Erik

@EriktheOutgolfer Teknik olarak, bu gerçekten 10 bit ROM içinde saklanabilir. İşte bir örnek özellik sayfası. (Bugün Intellivision homebrew oyunları için 16 bit ROM kullanıyoruz, ancak gün içinde bellek yongaları o kadar pahalıydı ki 10 bit kullanmak gerçek bir para tasarrufu idi.)
Arnauld

1

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

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

Çevrimiçi deneyin!

İçin +31 using System;using System.Linq;

Array.ReverseSatır içi kullanmayı umuyordum , ama öyle değildi (aşağıdaki alternatife bakın).

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

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

Çevrimiçi deneyin!

İçin +13 using System;

@JeppeStigNielsen Bu çözüm bakımı; satır içi her şeyin 3 bayt kaydedilmesini kısıtlama kaldırıldı.


Because you can save using System.Linq;, it can still be cheaper to use x=>{var a=BitConverter.GetBytes(x);Array.Reverse(a);return BitConverter.ToUInt32(a,0);}.
Jeppe Stig Nielsen

1

REXX, 42 bytes

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

Try it online!

Ungolfed:

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

ARM machine language Linux, 8 bytes

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

To try this yourself, compile and run the following on a Raspberry Pi or Android device running 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 bytes

Solution:

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

Examples:

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

Explanation:

There are no unsigned ints, so takes input as a long.

Convert into boolean array (64bits), reshape, reverse, take first 8 bytes, convert back to long.

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:

19 byte version in oK which you can Try online!

2/,/8#|12 8#(64#2)\
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.