大端或小端


57

编写一个程序或函数,该程序或函数输出L在小端架构上B运行的if 或在大端架构上运行的if。小写输出l还是b可以的。

没有输入。

计分是代码高尔夫,因此字节最少的代码获胜。

编辑: 根据下面的评论,我澄清一下,该条目必须能够在两种体系结构上运行。

我相信只有一个答案会受到影响,并且该答案已明确表明确实如此。


1
盒子的记忆。我不确定你的意思
利亚姆(Liam)

7
我认为这是一个有趣的挑战(这是不合常理的),但要对其进行测试将非常困难。尤其是由于大多数代码最终都将是特定于平台的。
DJMcMayhem

7
是的,我认为这会很有趣,因为希望与e-lang / golf语言相比,与e-lang / golf语言相比,“ elang”和“ golf”语言的使用困难。我觉得他们将不难验证。最糟糕的情况是他们应该可以手工验证
Liam

2
我想禁止基于特定机器码的答案?否则B0 4C C3,为mov al, 'L' / retunsigned char f(){ return 'L'; },将是有效的x86答案。
玛格丽特·布鲁姆

5
太棒了!针对通用编程语言具有竞争力的代码高尔夫挑战。
PellMell '16

Answers:


42

Python,33个字节

import sys
exit(sys.byteorder[0])

sys.byteorder'little''big'(对于在不看代码的情况下阅读此句子的人,则[0]表示第一个字符)。


挑战是输出必须是LB(或小写变体),而不是整个单词。
user2428118 '16

43
这就是为什么这样说sys.byteorder[0],即的第一个字符byteorder
s3lph

36

C,26个字节

a=66<<24|76;f(){puts(&a);}

假定32位int和ASCII字符。在amd64(小端)和mips(大端)上进行了测试。

GCC,23个字节

00000000: 613d 2742 0000 4c27 3b66 2829 7b70 7574  a='B..L';f(){put
00000010: 7328 2661 293b 7d                        s(&a);}

由feersum建议。多字符常量的值取决于实现,但这似乎在GCC中有效。在相同的架构上进行了测试。


7
短于可以a='B\0\0L';\0s替换为空字节。
feersum

1
@feersum多字符常量的字节序似乎与实现有关。我通常不会在代码编写中担心那么多,但是这个挑战全部在于区分实现。
Anders Kaseorg '16

该代码当前是否可以在GCC以外的其他工具上使用?
feersum

1
@feersum C89允许两者。
Anders Kaseorg '16

1
在运行AIX 5.2的RS6000上使用xlc(VisualAge C ++ Professional / C,用于AIX编译器,版本6)在26字节程序上成功打印“ B”
Jerry Jeremiah's


20

JavaScript ES6,50个字节

_=>"BL"[new Int8Array(Int16Array.of(1).buffer)[0]]

我不知道是谁决定让TypedArray对象公开解释器的本机字节序是一个好主意,但是到了。


5
WebGL人们认为这是个好主意,避免在传递给GPU时不必转换字节序。几乎所有人都认为这很愚蠢……:(
gsnedders '16

11

C,36 35字节

1个字节,感谢@algmyr和@owacoder。

main(a){printf(*(char*)&a?"L":"B");}
main(a){putchar(66+10**(char*)&a);}
main(a){putchar("BL"[*(char*)&a]);}

学分在这里

由于我没有大端机,因此未经测试。


2
C规范是否允许单参数main函数?
CodesInChaos

@codesinchaos是的。这将是给定的命令行参数数量。通常在这里用于初始化变量,1因为没有输入(程序名称始终作为第一个参数)
Liam

2
@Liam:如果允许使用0或2以外的任何值,则C11中定义了实现。

1
或者main(a){putchar("BL"[*(char*)&a]);}
owacoder

2
如果你陷入困境与呼叫约定,它下降到31: main(char a){putchar("BL"[a]);}
Andrea Biondo

8

Mathematica,22岁

{B,L}[[$ByteOrdering]]

这可能会违反一些关于不使用内置函数的规则,但是我对替代项并不十分感兴趣。


1
内置的很好(大多数答案也都使用它们)
Liam

2
再一次,Mathematica具有内置功能!
gcampbell '16

3
我认为这是一个片段,而不是程序或函数,应该添加&使其成为一个函数。(但是在什么构成“程序”方面可能存在分歧。)
Anders Kaseorg

1
@Anders我对PCG的当前标准不是很熟悉(如果有的话),但是恕我直言,解释语言的一个优点是代码段一个程序。它可以像Mathematica中的任何其他程序一样以独立方式运行。
威兹德先生

1
@ Mr.Wizard请注意,Mathematica中的“程序”是指独立脚本(需要显式打印),而此答案使用REPL。
LegionMammal978 '16

8

C,27

再长一个字节,但是无论如何这里是:

f(){putchar(htons(19522));}

它工作正常,请您向我解释一下。
ABcDexter

3
@ABcDexter 19522的二进制扩展是1001100 01000010(空格分隔字节)。现在,如果您占用每个字节,将其转换回以10为基数并检查ASCII表,您将看到此字节序列等效于LBhtons执行其操作,并且putchar只会打印LSB。在大端系统中,B小端系统htons将翻转字节,因此LSB为L
Kroltan '16

替换19522'LB'编译器警告和-1字节。
Stan Strum,

8

PowerPC机器码-20个字节

PowerPC是双字节序的(可以在启动时设置字节序),因此此代码应符合能够在BE和LE机器上运行的挑战要求。此函数返回1 'L''B'取决于当前设置的字节序。

作为功​​能,AFAICT符合SVR4 PowerPC ABI(由Linux在ppc32上使用),PowerOpen ABI(例如由AIX使用)和OS X ABI。特别是,它仅依赖于GPR 0是易失性暂存寄存器,而GPR 3用于返回“较小”值的事实。

00000000 <get_endian>:
   0:   7c 00 00 a6     mfmsr   r0
   4:   54 03 0f fe     rlwinm  r3,r0,1,31,31
   8:   1c 63 00 0a     mulli   r3,r3,10
   c:   38 63 00 42     addi    r3,r3,66
  10:   4e 80 00 20     blr

现在,它像这样:

  • 所述MSR读入GP寄存器0; MSR在第31位包含字节序设置(0 =大字节序; 1 =小字节序);
  • rlwinm提取物只是位:它需要在GPR0的值,- [R otates 由1所代替EFT(使得现在是在位置0)和与1(由那些31,31所产生的掩模要求它2); 结果存入GP寄存器3;
  • 乘以10的结果,总结66( 'B')(10 之间的差别'L''B'
  • 最后,返回给呼叫者

笔记

  1. 是的,这个问题确实要求打印,但是目前尚不清楚我应该如何打印预期在不同操作系统上运行的程序集中的内容。=)
  2. 对于那些感兴趣的人,请参阅rlwinm文档。几乎不了解PowerPC,我发现这种说明非常有趣。

    2018年更新:Raymond Chen发布了有关PowerPC架构的系列文章,您可以在此处找到有关rlwinm&friends的精彩文章。


7

Java 8、96、64 52字节

()->(""+java.nio.ByteOrder.nativeOrder()).charAt(0);

基于此答案的高尔夫。所有的功劳归@LeakyNun和@AlanTuning。Java保持松懈。

96个字节:

 char e(){return java.nio.ByteOrder.nativeOrder().equals(java.nio.ByteOrder.BIG_ENDIAN)?'b':'l';}

64个字节:

char e(){return(""+java.nio.ByteOrder.nativeOrder()).charAt(0);}

未经测试的b / c我无法使用big-endian机器。


1
char e(){return(""+java.nio.ByteOrder.nativeOrder()).charAt(0);}
Leaky Nun

char e(){return(""+java.nio.Bits.byteOrder()).charAt(0);}
Leaky Nun

@LeakyNun我在Java API中看不到Bits,当我运行它时,它给我“ Bits在java.nio中不是公共的”
蓝色

哦,那好吧。
Leaky Nun

如果使用lambda,则为52个字节!()->(""+java.nio.ByteOrder.nativeOrder()).charAt(0);
肖恩·怀尔德

6

Perl,38个36字节

say+(pack"L",1 eq pack"V",1)?"L":"B"

通过按系统的默认字节顺序打包数字并将其与按小尾数字节顺序打包的数字进行比较来工作。


6

(G)四十四字节

here $4200004C , c@ emit

假设单元格为32位(并且您的Forth解释器支持Gforth的基本前缀)。它仅将数字0x4200004C存储在内存中,然后在低端显示该字节。


5

C,34个字节

这假设ASCII字符编码

main(a){putchar(66+10**(char*)a);}

不带参数的电话。

说明:

调用时a将为1。*(char*)a访问的第一个字节a,在小端平台上为1,在大端平台上为0。

因此,在big-endian平台上,此代码会将66 + 10 * 0 = 66传递给putchar。66是的ASCII码B。在小端平台上,它将传递66 + 10 * 1 = 76,这是的ASCII码L


5

C#,60 52字节

C#在这一方面具有惊人的竞争力。

char e=>System.BitConverter.IsLittleEndian?'L':'B';

感谢Groo提供的C#6语法。

60个字节:

char e(){return System.BitConverter.IsLittleEndian?'L':'B';}

使用C#6语法,您可以将其缩短一点:char e=>System.BitConverter.IsLittleEndian?'L':'B';当然,这个(以及Java答案)实际上并不会输出该值。
Groo

欢迎来到编程难题和代码高尔夫球!这是一个不错的第一答案。
Alex A.

5

朱莉娅,24 19字节

()->ntoh(5)>>55+'B'

这是一个匿名函数,不接受任何输入并返回Char。要调用它,请将其分配给变量。假定整数是64位。

ntoh函数将传递给它的值的字节序从网络字节顺序(大字节序)转换为主机使用的字节序。在大型字节序计算机上,ntoh由于无需进行转换,因此是身份函数。在小字节序计算机上,字节被交换,所以ntoh(5) == 360287970189639680。也可能更可读地等于:0000010100000000000000000000000000000000000000000000000000000000二进制。

如果将结果右移ntoh(5)55,则在大字节序计算机上将得到0,在小字节序计算机上将得到10。并称,在字符常量'B',我们会得到'B''L'对或大或小端机,分别。

多亏了FryAmTheEggman和Dennis,节省了5个字节!


对于32位,您必须将55更改为23(同样,16位中的5应该是7)。我认为丹尼斯的意思是这样的:()->ntoh(5)>>55+'B'
FryAmTheEggman

1
f()='L'-ntoh(10)%16f()='L'-ntoh(10)&10应可在所有平台上使用。
丹尼斯


5

Common Lisp,27个字节

在SBCL和ECL上测试。对于一种可移植的方法,应该使用一些琐碎的功能

(lambda()'L #+big-endian'B)

#+符号是一个读取时间条件,即读出下一表格仅当条件表达式评估为真。这里的条件是#+big-endian全文,这意味着如果:big-endian关键字属于*FEATURES*列表(包含平台特定信息等在内的列表),则满足测试条件。以下表达式是'B,根据测试结果可以读取或跳过。如果您的平台是big-endian,并且您在REPL中编写了以上表格,则就像您编写了以下内容一样:

CL-USER>(lambda()'L 'B)

CL-USER>提示。)

函数的主体是一个隐式PROGN,意味着仅返回最后一个表达式的求值。所以上面的实际返回符号B。但是,如果读取时间条件评估为false,则该表单的读取就像您编写的一样:

CL-USER>(lambda()'L)

...只是返回symbol L


不允许使用摘要;而是编写完整的程序或函数。
暴民埃里克(Erik the Outgolfer)

@EʀɪᴋᴛʜᴇGᴏʟғᴇʀ更新,谢谢
coredump

注意:仅在OP明确允许的情况下,才允许使用摘要。
暴民埃里克(Erik the Outgolfer)'16

@EʀɪᴋᴛʜᴇGᴏʟғᴇʀ您能为此提供参考吗?在这里和/或shell片段中还有其他REPL答案,并且此中继文章将建议REPL答案默认情况下可以。谢谢。
coredump

5

ARMv6和更高版本:20字节机器代码

0xE10F1000 : MRS   r0,CPSR        ; read current status register
0xE3110C02 : TST   r0,#1<<9       ; set Z flag if bit 9 set
0x03A0004C : MOVEQ r0,#'L'        ; return 'L' if Z clear
0x13A00042 : MOVNE r0,#'B'        ; return 'B' if Z set
0xEBxxxxxx : BL    putchar        ; print it (relative branch)

未经测试,因为我没有合适的机器。CPSR的位9给出了当前的加载/存储字节序。


您可以使用函数(BX lr,是吗?)的返回值代替putchar,因为这r0是返回结果的正确寄存器。
anatolyg's

确实,(实际上是MOV pc,lr)在我以前的编辑中。但是,这满足了打印字母的要求,而不仅仅是返回字母。
user1908704 '16

我可能读错了引用,但是我认为可以通过“拇指2”指令编码来完成。这意味着第一条指令仍为32位(ARM v8参考手册的F7-2720页上的“编码T1”,将其设为0xF3EF_8000);第二个也是32位(对操作数进行编码有点奇怪,但是可以通过将“ i:imm3”设置为0010,将“ imm8”设置为00000010来完成,这给出的总指令为0xF010_2F02)。在第三条指令之前,我们需要插入“ ITE EQ”(0xBF0C)来控制接下来的两条MOV指令的条件,这些指令变为0x204C,并且...
Jules

... 0x2042(总共节省2个字节)。那么最终的BL指令有点难以表示,因为我们不知道的地址的位最终散布在我们知道的指令的位中,但这也是32位编码,因此结果将是总共为18个字节(F3 EF 80 00 F0 10 2F 02 BF 0C 20 4C 20 42 F ??????????)。我相信这会将体系结构更改为ARMv8及更高版本,尽管它可以在ARMv7(?)中使用。
2013年

4

Perl 5,21 +1 = 22字节

用运行perl -E

say ord pack(S,1)?L:B

在amd64(小端)和mips(大端)上进行了测试。


-E字节计数中是否真的需要该标志?您可以说您使用的是Perl 5.10(因为say该版本提供了此命令)
Paul Picard

1
@PaulPicard但是use 5.10.0;还有更多字节!
Anders Kaseorg '16

1
@PaulPicard您的观点是错误的。Perl 5.10需要使用-Eswitch或use语句say
Anders Kaseorg '16

3
-E在PPCG上“免费”。无需添加任何内容。
2016年

1
(但是-n-p没有)
法师

4

R,28 23字节

substr(.Platform$endian,1,1)

.Platform$endianbig如果在大字节序little上运行,而在小字节序上运行,则返回。在这里,使用substr,它返回输出的第一个字母,所以bl

作为endian唯一一个e包含在对象中的对象.Platform,由于与以下23个字节的代码部分匹配,我们可以减少它:

substr(.Platform$e,1,1)

3

Clojure,46 44字节

#(nth(str(java.nio.ByteOrder/nativeOrder))0)

这是一个使用Java内置函数获取计算机字节序的函数。然后获取它的字符串表示形式,该字符串表示形式将为"LITTLE_ENDIAN"或,"BIG_ENDIAN"并采用所选字符串中的第一个字符并将其返回。

由于@,节省了2个字节悬崖根


Clojure到底是什么,是Lisp还是Java?
Leaky Nun

@LeakyNun也许是与Java兼容的实用LISP?很难说。
2016年

#(nth(str(java.nio.ByteOrder/nativeOrder))0)短2个字节
悬崖根

3

红宝石, 3130个字符。

puts [1].pack("s")>"\01"??L:?B

嗯,一定是更好的方法。如果不需要输出char,请少计算5个字符,因为我认为其他解决方案可以省略打印。例如,如果您不想打印任何内容,请删除“放置”部分。


如果我没有记错,Ruby 1.9的后,您可以使用?L?B代替 puts :Lputs "B"
Sherlock9

我认为puts [76,66].pack("s")[0]会起作用。
韦恩·康拉德

@ Sherlock9,谢谢,少一个字符。@WayneConrad,也许添加您的答案,我手头没有大型endian机器进行测试,但是在little endian上它可以工作。但是这样的更改不起作用:puts [76,66].pack("s>")[0]。这意味着出于某种我不太了解的原因,可能无法从事大端字节排序。但是,这似乎是可行的(源自您的解决方案)puts [19522].pack("s>")[0]。WDYT?我想知道是否可以找到一些在大端上进行评估的地方。
akostadinov

las,我还缺少一台​​可以测试的大端机。
韦恩·康拉德

3

Bash(和其他unix shell),32(33)字节

第一次和第二次尝试:

case `echo|od` in *5*)echo B;;*)echo L;;esac # portable
[[ `echo|od` =~ 5 ]]&&echo B||echo L         # non-portable

多亏了丹尼斯(Dennis),缩短了版本:

od<<<a|grep -q 5&&echo L||echo B  # non-portable
echo|od|grep -q 5&&echo B||echo L # portable

echo实用程序输出带有十六进制值的换行符0A,而没有其他输出。因为<<<a61 0A

od默认情况下,该实用程序将输入解释为两个字节的单词,如果字节数为奇数,则将其填充为零,然后转换为八进制。这导致回声的输出解释为0A 00,将其转换005000为大端或000012小端。61 0A成为005141小端和060412大端。OD的完整输出也包括地址和尺寸数据意味着我们不能使用012用于测试。

该命令定义明确,可以公开系统的字节序。从标准

解释数值时使用的字节顺序是实现定义的,但应与相应类型的常量存储在系统内存中的顺序相对应。

相容性说明

我不确定是否在所有系统上都支持echo|od在反引号中使用双引号将其引起来的三字参数case。我不确定是否所有系统都支持不带换行符的shell脚本。我大都可以肯定,但是在big-endian系统上添加padding字节并不是od的100%。如果需要,echo a可用于便携式版本。所有脚本都可以在bash,ksh和zsh中使用,而可移植脚本则可以在破折号中使用。


不需要任何更改;只需在语言标题中放入一个可以正常工作的外壳,就可以设置好了。
丹尼斯

1
@Dennis我喜欢做那种分析的...虽然它更有趣,如果我找到的东西不标准,获取bash或zsh中比别人更短的答案。也许我会看看该怎么办[[
Random832 '16

1
分析没有错。最后一段听起来听起来像是您不确定特定于shell的答案是否有效... od<<<a|grep -q 5&&echo L||echo B是否可以在Bash和其他版本中使用。
丹尼斯

我在大端VM中对其进行了测试,并按预期进行echo|od打印0000000\n005000\n0000001
丹尼斯

@ user17752因为字节序不会影响的输出od -a
2016年

3

PHP,16字节

<?=pack(S,14)^B;

这使用了两个现有PHP答案中未使用的技巧:

  1. 传递给pack()或unpack()的值可以是任何值,而不仅仅是0或1。
  2. 按位XOR运算符(^)对字符串起作用,结果仅与较短的字符串一样长,从而避免了使用字符串索引或三进制运算符。

2

节点,42字节

n=>require('os').endianness()[0]

优点:有内置功能。缺点:属性名称很长


2

PowerShell,44字节

[char](66+10*[BitConverter]::IsLittleEndian)

字符66是B,后面10个字符是数字76 L1转换为数字时,布尔值“ true”变为。BitConverter是一个标准的.NET类。


1

球拍,35个 28字节

(if(system-big-endian?)'B'L)

'B'L分别。让我知道这是否不够具体:)



1

Haskell(使用仅GHC大小限制的数字类型),75字节

import Unsafe.Coerce
import GHC.Int
f="BL"!!fromEnum(unsafeCoerce 1::Int8)

(未在大端架构上进行过测试,但似乎应该可以使用!)


1

K,15个字节

    ("bl")@*6h$-8!`
    ,"l"

说明;

    From right to left;
    -8!`       /serialises the back tick and returns (0x010000000a000000f500)
    6h$-8!`    /This casts the result to `int which is type 6h(could have used `int$-8!`) - the result is (1 0 0 0 10 0 0 0 245 0i)
    *6h$-8!`   /* means first, we take the first item which is 1. Since it will be either 1 or 0, we can use it to index (@) into the two element list on the left i.e. ("bl")1 returns "l" and ("bl")0 returns b

1

Bash,27个字节

iconv -tucs2<<<䉌|head -c1

U + 424C)编码为三个UTF-8字节:E4 89 8C

假定iconv使用glibc中的函数,并且使用UTF-8语言环境。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.