엔디안 스왑


20

대부분의 사람들이 알고 있듯이 (바이트 주소 지정 가능) 하드웨어 메모리는 little-endianbig-endian의 두 가지 범주로 나눌 수 있습니다 . 리틀 엔디안 메모리에서 바이트는 작은 (최하위) 끝에서 0으로 시작하고 다른 한편으로는 빅 엔디안에서 바이트로 번호가 매겨집니다.

재미있는 사실 :이 용어는 요나단 스위프트 의 책 걸리버 여행 (Gulliver 's Travels)을 기반으로 Lilliputian 왕이 시민들에게 계란을 끊기 위해 명령을 내렸고 (반도의 엔디 언들) 반란군이 큰 결말을 깨뜨릴 것이라고 말했습니다.

스와핑 작동 방식

12648430다음과 같이 보일 수있는 빅 엔디안 시스템에서 메모리에 부호없는 정수 (32 비트)가 있다고 가정 합니다.

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

바이트 순서를 반대로함으로써 10 진수 인 16 진 정수 0xEEFFC000를 얻을 수 4009738240있습니다.

당신의 작업

부호없는 32 비트 정수를 10 진수로 받고 엔디 언을 교체 할 때 결과 정수를 출력하는 프로그램 / 함수를 작성하십시오.

규칙

  • 입력은 항상 범위에있을 것입니다 04294967295
  • 출력은 STDOUT으로 인쇄하거나 (줄 바꿈 개행 / 공간이 양호 함) 반환 할 수 있습니다
  • 입력과 출력은 10 진수입니다
  • 유효하지 않은 입력에 대한 동작은 정의되지 않은 상태로 남아 있습니다.

테스트 사례

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

함수 응답의 경우 "입력 및 출력이 10 진수입니다"는 숫자 문자열 또는 숫자 값 배열이 필요함을 의미합니까? 아니면 함수가 언어의 자연 정수 값 표현을 사용할 수 있습니까? 대부분의 경우 "소수"와는 전혀 관련이 없습니다.
aschepler

1
@aschepler 언어의 정수 값입니다 (예 : 42십진수로 표시되지만 기술적으로는 C에서 이진수로 표시됩니다. 물론 type 0x2a을 피할 수 있습니다. 입력을 문자열 등으로 입력 "2a"하는 것입니다.
ბიმო

관련 (이 도전은 32 비트로 먼저
채워야 함

답변:


25

x86_32 기계 언어, 3 바이트

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

이것은 약간의 속임수입니다. 파스칼 레지스터 호출 규칙 ( Wikipedia 참조 )은 __fastcall과 비슷하지만 eax의 첫 번째 매개 변수를 전달하고 eax는 리턴 값도 포함합니다. 또한 호출 수신자 정리이지만 리턴 포인터 이외의 다른 용도로는 스택을 사용하지 않으므로 별도의 조치를 취할 필요가 없습니다. 이를 통해 mov 또는 xchg를 피하고 bswap을 직접 사용할 수 있습니다.


bswap80486 이상 이 필요합니다.
ceilingcat

@ceilingcat 매우 사실이지만 컴파일러 또는 툴체인 제한으로 인해 다른 많은 솔루션의 경우에도 암시 적입니다!
다항식

10

x86_64 기계 언어 Linux, 5 4 바이트

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

-1의 @peter ferrie 에게 감사합니다 .

온라인으로 사용해보십시오!


10 진수 반환 값이 아닙니다. 나는 그것이 중요하다고 생각하지 않습니다. 게다가, 당신은 4 바이트 동안 edi, eax를 xchg 할 수 있습니다.
피터 페리

@peterferrie 와우, 방금 PE 헤더에 대한 정보를 웹 사이트에서 탐색하고있었습니다!
ceilingcat


6

Japt , 10 14 바이트

sG ùT8 ò w ¬nG

시도 해봐


설명

입력 정수를 밑이 16 인 문자열 ( sG)로 변환 0하고, 시작을 길이 8 ( ùT8)로 채우고, 2 개의 문자열 배열 ( ò), 역 ( w)으로 다시 나누고 , 문자열 ( ¬)로 다시 결합하고 밑으로 다시 변환하는 데 사용하십시오. 10 ( nG).


편리한 기능은 y함수에 함수가 주어지면 정규 변환을 적용하고 함수를 실행 한 다음 변환을 뒤집는 등의 더 많은 함수를 갖는 것 입니다. 이 경우 sG_ò w ¬8 바이트 로 단축 할 수 있다고 생각합니다 . 아니면 그렇게한다면 7 일 ò수도 있습니다 sG_ò2_w.
ETHproductions

@ETHproductions 지원합니다. 언더 &.J의 부사는이 작업을 수행하며 골프에 가끔 정말 도움이됩니다. 그러나 모든 역전에서 코딩하는 것은 지루할 수 있습니다.
cole

@ETHproductions : "오버로딩"이 많을수록 더 좋습니다 :) 파인트를 당기면서 이것을 작성했으며 원래는 sG_òw...내 인생에서 왜 작동하지 않는지 알 수 없었습니다! 나는 내 실수를 깨달았다!
Shaggy 2013

2 << 24 미만의 입력에는 작동하지 않는 것 같습니다 ...
Neil

감사합니다, @Neil; 나중에 고정시킬 것입니다. 4 바이트가들 것 같습니다.
Shaggy



5

APL + WIN 14 바이트

256⊥⌽(4⍴256)⊤⎕

설명

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

1
겠습니까 256⊥⌽⎕⊤⍨4⍴256-1 바이트 작동?
Outgolfer Erik

대답은 '노하지만 잘 Dyalog APL에 대한 예가 될 수 있도록 ⍨ 연산자는 APL + WIN에서 사용할 수 없습니다 없습니다
그레이엄

5

C # , 70 68 바이트

이것은 아마도 최적이 아닙니다.

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

온라인으로 사용해보십시오!


할당을 return표현식 으로 이동 한 다음 표현식 본문 멤버 구문을 사용할 수 있습니다 ( uint e(uint n)=>((n=n>>16|n<<16)&0xFF00FF00)>>8|(n&0xFF00FF)<<8;64 바이트).
hvd

@ hvd 그것은 유효한 표현 본문 구문으로 표시되지 않습니다. 그러나 시프트 재배치 트릭을 사용하여 2 바이트를 줄일 수있었습니다.
다항식

나는 오타 나 그와 비슷한 것이 없으며 내 의견에 정확히 맞는 방식으로 내 의견에서 TIO 링크로 복사하여 붙여 넣었습니다
.TIO

나는 0xFF00FF00이 0xFF00FF의 보완 물이라는 것을 알았고 그것을 활용할 수 있는지 궁금하십니까? 그러나 변수를 선언하면 너무 많은 문자가 필요합니다
PrincePolka

오! 당신이 사용할 수 있습니다 : 좋은 참 상수를 확인 0xFF00FF하여 두 번 >>전에 보내고 &보내고, 당신은 다음 단축시킬 수 0xFF00FF~0u/257: uint e(uint n)=>((n=n>>16|n<<16)>>8&~0u/257)|(n&~0u/257)<<8;(60)에 대한 TIO 링크
HVD


4

05AB1E , 12 10 바이트

3F₁‰R`})₁β

온라인으로 사용해보십시오! 설명:

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

1
This doesn't seem to be a valid solution. The "padding" you do is actually repeating the list of bytes to length 4.
Erik the Outgolfer

@EriktheOutgolfer Bah, I wish the documentation would actually say that...
Neil

3

JavaScript (ES6), 45 43 bytes

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

1
Starting with t=0 saves 2 bytes: f=(n,p=t=0)=>t++<4?f(n>>>8,p*256+n%256):p
Arnauld


3

MATL, 12 10 bytes

7Y%1Z%P7Z%

Try it online! Or verify all test cases.

Explanation

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

Saved 6 bytes with @Neil's help

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

Test cases


Nice, best I could get with recursion was f=(n,p=0,t=4)=>t?f(n/256|0,p*256+n%256,t-1):p.
ETHproductions

@ETHproductions ...that's shorter?
Erik the Outgolfer

1
@ETHproductions That's definitely shorter. You should post it.
Arnauld

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

1
@hvd No worries. You can either add it as an alternate version or replace the existing one entirely. Up to you!
Arnauld

2

J, 16 bytes

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

Try it online!

Working on shortening the right-hand expression. I think I can shave off a few bytes by making this work with a beta J version. I swear I saw on here that you can end a train with a noun in a new beta version...

Explanation

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

Convert to 4 digits base 256, reverse the digits, then convert back to decimal. Basically, perform the algorithm that is provided in the OP. This is perhaps the one time where it's helpful that J's mixed base conversion requires you to specify the number of digits, although it would be 2 fewer bytes if I could end the train in a noun ((#:~4#256) instead).


2

Excel VBA, 103 92 Bytes

Anonymous VBE immediate window function that takes input from range [A1] converts to hex, reverses bytes, and outputs to the VBE immediate window

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

Can I test this somewhere? Could you add an online interpreter, please?
ბიმო

2
@BruceForte No, unfortunately there are no online interpretters for any of the variants of VBA, however, if you have a copy of Excel on your computer, you can access the VBE by pressing Alt + F11, and then the immediate window by pressing Ctrl + G. For this anonymous function you would then paste your input into cell A1 and the code above into the immediate window and press enter
Taylor Scott

Oh - and sometimes VBA is a bit funky (and the Mac version is imperically worse than the windows version) so this, and unless otherwise stated all, VBA solutions assume the default 32-Bit Windows version
Taylor Scott

2

PPC Assembly (32-bit), 8 bytes

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

How this works:

  • PPC calling convention puts the first 32-bit word parameter into SP+24, and shadows that address into GPR3.
  • LWBRX takes load GPR3 (third operand) and zero-extends it (second operand) into EA, then reads 4 bytes in reverse order and stores it into GPR3 (first operand).
  • GPR3 holds the return value.
  • BLR returns from the function (branches to the address in the LR register)

Unfortunately there aren't any online PPC assembly emulators that I could find to demonstrate. Sorry!


2

Befunge, 62 61 or 49 bytes

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

Try it online!

This is using standard Befunge on the reference interpreter, and we thus need to account for the fact that memory cells are 8-bit signed, and correct for possible signed overflow.

On implementations with unsigned memory cells (e.g. PyFunge), or where the range is greater than 8 bits (e.g. FBBI), we can get away without those checks, saving 12 bytes.

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

Try FBBI online!
Try PyFunge online!

Although note that PyFunge has a bug processing integer input, so when testing on TIO you need to follow the number in the input field with a space or line break.


2

Octave, 10 bytes

@swapbytes

Try it online!

This may be the first time that Octave has the exact same score as its golfing derivative, MATL. Of course, in this case, it's Octave that has the built-in, rather than MATL, making it a lot easier.

Defines a handle to the built-in swapbytes, which takes any data type, swaps the endianness and outputs the result. In this case, the input is a 32-bit unsigned integer.



2

R, 86 bytes

I thought there was already an answer (or two) in R for this question, but I must have been mistaken or they had the same issues that I had with R not doing signed ints. That issue took out any builtins that could have helped. I tried the 256 base conversion, but it ended up being to long, but I think there is still room for someone smarter than me to do that. Then I ended up with the following which it a base 2 conversion swapping the order in a recursive function.

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)

Try it 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

you were right about base 256 being shorter!
Giuseppe

@Giuseppe, you are going to put hat one up aren't you
MickyT

2

R, 41 bytes

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

Try it online!

Verify all test cases!

Uses a base-256 conversion as MickyT suggested here. R does not have unsigned 32-bit integers, nor does it have 64-bit integers. This prevents us from using bitwise operations but this approach (and likely MickyT's) is probably still shorter since R's bitwise operators are quite verbose.

Utilizes number 4 of this tip, taking into account that we're never getting a number as large as 256^4.

n%/%256^(0:3)%%256 extracts the bytes, and %*%, the matrix product, is the dot product in this situation, with 256^(3:0) effecting the reversed order of bytes. %*% will return a 1x1 matrix containing the endian-reversed value.


1

CP-1610 assembly, 6 DECLEs = 8 bytes

This code is intended to be run on an Intellivision.

A CP-1610 opcode is encoded with a 10-bit value, known as a 'DECLE'. This function is 6 DECLEs long, starting at $480C and ending at $4811.

The CP-1610 has 16-bit registers, so we're using two of them (R0 and R1) to store a 32-bit value.

                               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

Execution dump

 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

Why is this 7.5 bytes? I think it should be 8 bytes.
Erik the Outgolfer

@EriktheOutgolfer Fair enough. Updated accordingly.
Arnauld

@EriktheOutgolfer Because 60 bits equals 7.5 bytes?
Jeppe Stig Nielsen

@JeppeStigNielsen That's true, but a file can never be 7.5 bytes long, it will be pre- or post-padded with 0s.
Erik the Outgolfer

@EriktheOutgolfer Technically, this could really be stored inside a 10-bit ROM. Here is an example spec sheet. (Today, we're using 16-bit ROM for Intellivision homebrew games, but back in the day, memory chips were so expensive that using 10-bit was a real money saver.)
Arnauld

1

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

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

Try it online!

+31 for using System;using System.Linq;

I was hoping to use Array.Reverse inline, but it wasn't to be (see alternative below).

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

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

Try it online!

+13 for using System;

This solution care of @JeppeStigNielsen; removing the restriction of having everything inline saved 3 bytes.


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)\
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.