|
点击上方“C语言与CPP编程”,选择“关注/置顶/星标公众号”
4 f, `" M2 _. ]7 e9 z干货福利,第一时间送达!! s2 { t% Q- O5 q3 Q. T1 M9 B5 s
- H0 S, d' O& S/ Y6 P, h
ywrehzkgavv640106051732.png
' p6 C( q: a6 o$ _
转自:CSDN(ID:CSDNnews)
# `$ E) |# A* ?; m& ^: }8 u看到这个标题,相信大多数人的第一反应是:真的有人用 40 亿条 if 语句,只为判断一个数字是奇数还是偶数?/ d M! _( X! I2 X5 I
的确有,这个开发者名为 Andreas Karlsson,他还把整个过程都整理成文了。( P! I3 z4 i1 M2 s: d) o
15l22ligikm640106051832.png
* x0 k; X6 U" ]- S% T! E. J或许由于这“40 亿条 if 语句”听起来实在震撼,Andreas Karlsson 分享的这篇文章在 Hacker News 上很快引起了极大的关注和讨论,而他在文中也直白表示:其实这个想法,最初源于一个充满恶评的短视频。
% Y! a$ Q5 L7 u" U/ Z) C
aw5bpvdwhyl640106051932.png
3 t# D, n$ i2 B ^; d
以下为译文:
6 Z" Y b7 w- M. s" _' s9 {* V6 q
cni3nad0fs1640106052032.png
& n8 R* n- \; w' u; U1 n5 f
大于 11 的数字,没有输出结果$ V9 w7 K x9 P# v) D9 w( Q# E
我最近在火车上刷手机时,偶然发现了上面这个截图:“写了一个程序,来判断一个数字是偶数还是奇数。”点开评论区,果然是一连串的恶意评论,多数都在嘲笑这位新手程序员的稚嫩和无知,竟企图以这种方式解决计算机科学中的经典问题“取模运算”。
" A6 O7 G& R5 b9 M. V# k/ F可看过截图中的代码和网友评论后,我莫名生出了一些不同的想法:现在,AI 正在分分钟取代程序员、抢走他们的饭碗,并彻底改变了我们对代码的思考方式,或许我们应该更加开放地接受这个行业新生代的思想?% G9 P0 T+ v$ `
其实仔细想来,上述代码是时间和空间的一种完美权衡:你在付出自己时间的同时,也换来了计算机的内存和时间——这难道不是一个神奇的算法吗?$ S$ r4 t1 K; h: z5 f6 d$ P
于是,我开始探索这种只使用比较来判断一个数字是奇数还是偶数的想法,看看它在实际情况中的效果到底如何。由于我是一位高性能代码的忠实拥护者,因此我决定用 C 语言来实现这个想法。
t0 {8 [7 |2 H- ?( F然后,我就开始编码了:
& m. O0 U1 L* Z2 p$ L: c, ~/* Copyright 2023. All unauthorized distribution of this source code . H+ i4 N( f1 B$ p) ^6 P+ Z4 X
will be persecuted to the fullest extent of the law*/+ z+ U$ w5 r. A
#include + S1 w8 g; _% z9 D
#include
- z) O" O9 y8 a4 t$ G#include
! D+ k, r! Q8 w1 w0 [- j q' Yint main(int argc, char* argv[])8 R8 l9 P% Y! i1 ^
{8 g5 r9 Q& M" ^7 [# Q
uint8_t number = atoi(argv[1]); // No problems here
8 |: V1 }( F- F( a' t+ R$ W$ { if (number == 0)+ A" T! k* Q$ }8 s3 H
printf("even# h+ ^/ M: G: J
");
, B" ?, S3 }. @% l! @ if (number == 1)
* p( {# @4 k, z3 E2 ^, Y0 x printf("odd: l9 A) F3 {3 ?6 @
");$ U. o1 ~' H) n6 I. a0 C; o; o
if (number == 2)" ?- O5 `# X1 o3 ^; E: u
printf("even/ l* G6 D2 A0 S; D4 e7 @. f' ~
");; j7 J q& K4 u0 ^) Y& ]
if (number == 3)
9 v, u, A) v) I1 x6 y, _" J% G printf("odd3 D7 G1 ^* O* `
");8 @6 C$ s% E! g9 ~$ f. \1 f
if (number == 4)
/ Y' u, a0 p6 m: b2 N1 u5 k printf("even
7 E4 i1 F4 Q9 P' O* c# z");8 y/ w/ P: L$ C6 o. [- K' ]/ N* ^
if (number == 5)
2 K. h+ V' |: c* y% S8 F ? printf("odd
0 W5 m; J' ^$ N$ u. o");
* | i. C+ P# d if (number == 6)
- d9 x$ K0 p+ }+ Y j( h printf("even }3 {" j) j' S" o
");+ u' K3 w9 G' X7 ^: x7 v
if (number == 7)
$ t* n# u$ T" b- C; O printf("odd9 F% [+ R+ T( `! J' X4 c3 R V
");4 }. E9 y {6 K) X& V- g! Q: @
if (number == 8)
. `& G* }8 o$ X" A printf("even& S0 {7 `* X6 k9 u& |
");0 Y. t" M2 `9 E% L
if (number == 9)
! } Q3 U% S }5 ^* _& \$ k: Z8 s printf("odd
# e K* B, F$ j4 m7 {* C$ t4 w");
" @" X0 H1 i8 | if (number == 10)% z( W- g. b& ^% v3 Q$ \$ \" { G$ C
printf("even
9 Q- e2 t. L: t% ^9 P6 u. { K1 F");: X* K* \% u/ s+ A) S( w' W
}
! N$ X7 C; v# U接下来,我们要编译这段代码,使用 /Od 禁用优化,确保烦人的编译器不会干扰我们的算法。编译完成后,我们就可以对程序进行快速测试,看看结果如何:
: R+ P' X! v; _5 x8 iPS > cl.exe /Od program.c
, L) j% b, K2 P8 ^) gPS > .\program.exe 0
4 M6 `2 o: O9 L+ Qeven
1 o5 s1 S8 H9 l X' _( @2 G0 ^PS > .\program.exe 46 M1 N6 D. [" r1 A' a
even
% l! w0 p. k& g- F- P+ NPS > .\program.exe 3& R9 R8 F$ M1 H
odd5 G$ ]3 w" O3 W0 L9 c& l% c3 J
PS > .\program.exe 7
3 b1 V# i7 u% _odd7 v6 ^1 y0 \5 W% W: B9 h
结果显示:0、4 是偶数,3、7 是奇数。这么看来,程序似乎运行得挺好,但在进一步测试后,我发现了一些问题:
* I2 t' \9 ~) b( x8 K- BPS > .\program.exe 50
/ R: [. x# h$ H* Z% R; L0 f9 RPS > .\program.exe 11
3 T( F- w. c$ w7 g3 XPS > .\program.exe 997 U' u8 ]1 s$ R- a
+ F5 d/ r& x( g' e3 |
大于 11 的数字没有输出,看来这个程序只对 11 以下的数字有效!回到原始代码中,可以发现问题出在最后一个 if 语句之后:我们需要更多的 if 语句!
$ Q) t- C& V: K( H
aveoj23prhh640106052132.png
' h" ^( _' q1 t' I# `向 32 位(32-bit)数扩展
9 w" c' A% w# B4 }, H这件事进行到这里,就需要我在时间和内存之间做出权衡了。考虑到我的寿命有限,我决定用另一种编程语言对 if 语句进行元编程。为了弥补这种“作弊”行为,我决定用“地球上速度最慢”的语言 Python。
& p I+ W1 {4 ?6 y0 c% |print("/* Copyright 2023. All unauthorized distribution of this source code")% Z T- ^) Y& y8 u) m8 |9 Z
print(" will be persecuted to the fullest extent of the law*/")
' V# R( f2 c8 I8 U* Q4 p* o, N1 }0 z1 I
print("#include ")
. Q A4 A# y6 `8 a, Aprint("#include ")
$ s$ L* ~* ]' q& K( ~) r8 pprint("#include ")
! E4 f3 C( b' B3 g: q5 b2 K0 D3 e
print("int main(int argc, char* argv[])")
3 `" F. Z% `2 h/ v) mprint("{")
4 e; k- C- I; eprint(" uint8_t number = atoi(argv[1]); // No problems here")! |0 N9 o6 Q* J. A
8 i3 L: e% b. n1 Ufor i in range(2**8):
) ?8 F$ {1 q: G& C" ~: k7 L+ S print(" if (number == "+str(i)+")")/ L! D% H0 Z. T' ^
if i % 2 == 0:7 i2 D& J8 q w3 O( P
print(" printf(\"even\n\");")
7 g# ^/ C Q' y5 ?% `7 {( o | else:, M4 s- a1 ^) S* K+ M$ z: p& {
print(" printf(\"odd\n\");")
" v5 d3 Q) w' x- g* {print("}")
G$ K) w; C% H! S好了!现在我们可以生成一个程序,解决所有 8 位(8-bit)整数的奇偶问题!
; ~1 @- E8 A8 e) l. vPS > python programmer.py > program.c# \6 Q& e5 W7 @& m
PS > cl.exe /Od program.c
" r1 b& F0 ^! U2 _PS > .\program.exe 99
7 M" b" s; W& d2 s: r0 j8 j7 r% l# S: Wodd
" g$ W1 @4 z8 \6 UPS > .\program.exe 50* u! Z! _& C% R! Y
even
7 C. V: v7 H2 g. [* ]$ q9 r% Q. n' MPS > .\program.exe 2409 w0 d/ P5 J; t/ Y' z
even. y1 n3 P9 P- @5 `8 p1 u
PS > .\program.exe 241; f5 u8 a! A# ~' `1 E0 f
odd
% k& Q, n* ?$ i8 K看看,这个效果简直完美!现在,让我们把它放大到 16 位(16-bit)!
; @- T0 M1 H; R4 n2 x( P" Y4 ]print(" uint16_t number = atoi(argv[1]); // No problems here")
' }+ [5 n$ Y$ R3 W% y2 b…
/ J3 u% I9 a& {% q" B! Ufor i in range(2**16):* o+ A' e0 x! ], _; E; q9 E
6 G* x# N8 ^+ W" M* s4 {0 M
这样就得到了一个约 13 万行、超长且漂亮的 c 文件。回顾了一下我多年工作所做的一些代码库,这其实不算什么。话不多说,开始编译!3 L$ }4 D' n* R
PS > python programmer.py > program.c
- y6 G# O! c+ L! k, B/ h7 cPS > cl.exe /Od program.c; ]0 L# k$ f, I' ^
PS > .\program.exe 210009 \9 V( U+ Z* O( C/ p' w
even
s1 f! l3 H, B: b7 p* a. dPS > .\program.exe 3475 + R. G3 v0 J6 ]# Q$ i- v0 G
odd# w2 h% j I3 K4 S& @9 v, U
PS > .\program.exe 3 ( C8 m% E- D/ B2 H5 [4 S
odd+ ~, r2 t1 Q, A6 L/ E& E2 U0 B5 y" W
PS > .\program.exe 65001
) ?+ m4 _' F8 m& V, w, S4 ?odd
8 C3 q& p$ a( s1 |( ~PS > .\program.exe 65532' B# @9 Y7 h {! b! q4 o" b+ P
even: d6 d* D) a3 _$ \9 `' [' z
太棒了,我们的算法似乎能够处理大量数据!可执行文件大约只有 2 MB,但这与我拥有高达 31.8 GB 内存的强大游戏设备相比,简直不值一提。
' p6 |" q$ A4 d4 D但众所周知,32 位(32-bit)才是计算机领域的终极目标,也是我们解决所有实际工程和科学问题所需的最终位宽。毕竟,在 IPv4 因所谓的 "地址耗尽 "而被认为过时 60 年后,它如今仍然很强大。所以,让我们来看看最终的规模:32 位的数字是 16 位的 65536 倍,这会有什么问题吗? `: \ n1 @+ y$ ]5 w9 _9 X
print(" uint32_t number = atoi(argv[1]); // No problems here")
% u, F* J3 l! N; H; \…
4 H3 p. ?; {0 l5 afor i in range(2**32):( K) L1 c4 ^! N) a
于是,我让强大的 Python 开始它的工作。48 小时后,我喝了一杯咖啡,然后回来检查程序,就得到了一个美丽的 c 文件,大小接近 330 GB!我几乎可以肯定,这是历史上最大的 c 文件之一。当我输入下一条命令时,我的手指都在颤抖,我猜 MSVC 肯定从未遇到如此强大的源代码。
0 v/ o+ T; ~. {' m" z, v在我那台可怜而强大的电脑页面文件中遭受半小时的折磨后,输出如下:
1 m2 [+ X1 h, h3 v4 x k: NPS > cl /Od program.c
; l* \6 [4 _: s2 ?Microsoft (R) C/C++ Optimizing Compiler Version 19.32.31329 for x646 M8 e2 e, \3 Q, |+ [' x4 y# [
Copyright (C) Microsoft Corporation. All rights reserved.9 Y0 s! e9 K% ] s8 Q" p" O! v' o
! C3 r3 |; k: Q) `1 x4 T8 `program.c
* k# e& A2 F2 x0 w8 Gprogram.c(134397076): warning C4049: compiler limit: terminating line number emission
3 }6 h9 z7 o5 b4 F6 |( aprogram.c(134397076): note: Compiler limit for line number is 16777215
/ D+ W# \* {% | eprogram.c(41133672): fatal error C1060: compiler is out of heap space6 a( ?2 j9 K* O; S2 ]1 Q% f
太令人失望了!不仅编译器让我失望,在研究 Windows 可移植可执行文件格式(.exe)的限制时,我发现它无法处理超过 4GB 的文件!由于需要将 40 多亿次比较语句编码到可执行文件中,这对于实现我们的算法是一个主要障碍。即使每次比较时使用的字节数少于一个,对我来说工作量也太大了。% a4 b8 e" R$ j
不过,糟糕的编译器和文件格式不应该阻止我们实现梦想。毕竟,编译器所做的只是将一些花哨的机器代码写入文件,而文件格式只是一些结构,告诉操作系统如何将二进制代码放入内存——其实,我们自己就能做到。
( Q$ ?# o# d% C) _6 r2 C
sxosmui3bor640106052232.png
7 g& a \5 g% a! H! o2 j/ ~/ D解决最后一个问题,程序性能很不错/ }/ A8 j5 u* B% x6 e p1 Q. f
让我们先用 x86-64 汇编语言编写一个 IsEven 函数,因为这是我 Intel 处理器驱动的本地语言,它看起来是这样的:
$ Y/ B7 I F8 Y7 f; l; Argument is stored in ECX, return value in EAX
% a* }$ p* { E4 P9 ]+ f3 _XOR EAX, EAX ; Set eax to zero (return value for odd number)
5 K( i0 j8 M0 x8 e% V& E: ZCMP ECX, 0h ; Compare arg to 0 " W# D$ G/ X3 t% z' O3 ~7 t
JNE 3h ; Skip next two instructions if it wasn't equal: p! _8 D @# ~7 x2 M) U* e
INC EAX ; It was even, set even return value (1)
7 U3 v% v" x8 S- J+ T( WRET ; Return
4 e- T `8 o* t r' z0 sCMP ECX, 1h ; Compare arg to 1' c. m" x1 e* o6 D7 F3 K6 n
JNE 2 ; Skip next instruction if not equal" p' M* f& [% M; k
RET ; Odd return value already in EAX, just RET
& B+ `- |$ G+ Q; h- Q9 I: B a: W; add the next 2...2^32-1 comparisons here0 m# a6 E; O& d- M- n8 P. a
RET ; Fallback return. v p* {! T- d: {
这并不是真正正确的汇编代码,但这不重要,因为我们要手动将其编译成机器代码。
# U, o) P8 ~9 l- _你问我是怎么做到的?我上网查阅了x86(-64) 体系结构手册,还利用我早年编写仿真器和黑客经验,找出了每条指令的正确操作码和格式……开个玩笑,这是不可能的。实际上,我是直接问 ChatGPT 每条指令的正确操作码是什么,幸运的是,它也没有产生 x86-64 的任何新扩展。
/ E! ?$ ~+ q- F5 Q1 F' @所以现在我们只需编写一个“编译器”来输出这段代码。请注意,我们将直接使用从 AI 获取的指令操作码,下面是用 Python 编写的代码:: d# J& z" z, L6 D$ B2 Q4 }6 o
import struct1 _. r+ w; z0 a+ m
with open('isEven.bin', 'wb') as file:
9 H* j0 U% k2 C$ P file.write(b"1à") # XOR EAX, EAX0 Q( Z( C& h0 J* c
/ Q: p1 b i' ~. ]5 v" z
for i in range(2**32):
' v' z: z9 u1 T" h+ @3 k+ p; w ib = struct.pack("[I], i) # Encode i as 32 bit little endian integer0 d) a2 i1 |6 L! l z
" x' w: ^6 X/ W& a
file.write(b"?ù" + ib) # CMP ECX, i
, T4 n& N3 v) r4 e* W
! ^: E8 z1 o7 ^8 E if i%2 == 0:/ P; F0 e" t* ^# G
file.write(b"u") # JNE +3
- ]/ I2 }2 v4 Q! i6 _; a file.write(b"?à") # INC EAX% A6 {$ X7 U( @& }: H( u/ n
file.write(b"?") # RET+ e1 H3 S! h7 k. O/ K
else:4 l$ O: ?; s; g) Z
file.write(b"u") # JNE +1$ Y3 ~/ t2 h: N1 ?- h
file.write(b"?") # RET
+ u* K8 }/ @( o
6 b: n5 K E) W1 Z file.write(b"?") # Fallback RET6 P/ l- ~, ?" l: m
虽然我们在一定程度上偏离了开头 TikTok 帖子的最初构想,但本质并没有改变:我们创建了一个非常长的 if 语句列表,用于确定某个数字是奇数还是偶数,并忽略了任何有助于简化问题的算术运算。1 Y p d) U& B- s G* u8 s
运行这个程序后,我们就得到了一个 40GB 的文件,其中包含了确定 32 位数字是偶数还是奇数所需的全部 42 亿次比较!现在,我们只需编写能够加载和使用这些指令的主程序。为了提高性能(这一点非常重要),我决定将文件映射到地址空间,而非一次性读取全部文件。这样,我们就可以假装整个文件已经在内存中,让可怜的操作系统来处理将一个 40GB 的 Blob 装入虚拟内存的问题。用 READ 和 EXECUTE 权限映射文件后,我们就可以使用函数指针调用代码了,代码如下:
4 S; c8 q3 _, c3 g4 J ~- b#include
: e7 E2 H7 @+ |) p0 [" ?+ f- Z#include
- r4 [1 @2 ]' p#include
( J3 _! t! p2 k! r: y5 Y9 z# O6 |* R& q3 a! C! A$ {0 ?2 i4 d
int main(int argc, char* argv[])1 H& P+ T( |8 `
{
" A# T! t. S! ^) l uint32_t number = atoi(argv[1]); // No problems here V" H8 P) u, W4 L1 q
9 z; n& T% g! L0 m9 t
// Open code file1 [; P( A/ J' M; f3 `0 P
HANDLE binFile = CreateFileA(6 E0 S( ]6 N6 T- ^) _( g9 F! j7 O2 T4 X
"isEven.bin",, Y4 I7 H3 l+ K. b. s
GENERIC_READ | GENERIC_EXECUTE, FILE_SHARE_READ,
+ s' Z) G+ W; A% D NULL,) P1 h/ F5 r3 L
OPEN_EXISTING,
1 X: q- H: A0 a! o( Q. k9 o FILE_ATTRIBUTE_NORMAL,2 D U$ q2 N I
NULL);9 N* \% u8 u. t3 U$ ~2 ^4 m, k
// Get 64 bit size of file. E! g$ t) r) J, ?9 S3 I& b' U
LARGE_INTEGER codeSize;: D% C* c- I8 Q
GetFileSizeEx(binFile, &codeSize);# P+ l. G9 `4 f8 T S
, ]) S# a1 G$ \7 J
// Create memory map of the file
o* @' J" ~+ y; F HANDLE mapping = CreateFileMapping(
5 X( G n2 q3 O9 b/ u! \' P binFile,$ z2 U8 ?5 v8 Q' x% Y
NULL,
/ D) V9 b( u/ K9 r6 O' @ l PAGE_EXECUTE_READ,
8 `8 B/ j- M% d' e( P2 v9 G% e0 O 0,
2 h: Z$ X$ \" m: p 0,
2 r) a+ S5 G9 P) \ NULL);/ z% Y& W+ U, s
2 g! `! X3 h, U+ e$ S // Get a pointer to the code8 X9 }3 {$ N$ z+ O, x
LPVOID code = MapViewOfFile(
2 w1 U; j% D$ m' M; O2 X0 O( K, ]7 ^3 c mapping,FILE_MAP_EXECUTE | FILE_MAP_READ,7 l& b* I( k+ @1 D$ ?
0,
+ y) L$ V# E& F1 a- | 0, z) J& L, F) _. k: l: J
codeSize.QuadPart);6 @: ~7 }9 J) [5 v1 X
- Y9 i- T5 ?' O3 q" d1 h1 n
// Create a function that points to the code
# U- `5 z- i) _, p* @' P# D7 H- d int (*isEven)(int) = (int(*)(int))code;% i$ a: l1 W8 I4 v
1 K( t0 v+ ~0 p) a7 ^( z
if (isEven(number))0 e) R$ j+ `, ^! R5 b& D( V3 O
printf("even) I' {" `& ^6 ?. J% }
");
) r5 w# z+ V$ z" d! \5 J3 @ else
' ~1 r r- h+ L2 U) S printf("odd; R/ j( g1 {% y+ ~, ~( C" k
");, W/ M! R4 x q/ e; D8 K9 W3 Q
: @+ c" O5 p# v( y) D
CloseHandle(binFile);1 b8 X, N" g: a& P+ X0 f
}- N: _5 d+ }( C* U. ?" F9 w) ?
就是这样!现在我们已经具备了判断任何 32 位(32-bit)数字是奇是偶的所有功能,让我们试一试:
5 h! j4 Y) z+ j7 D% E6 i+ pPS >.\program.exe 300" i& X8 Q. l" F3 ]; ^' v# P
even5 Q" ?* Y7 _0 J8 q0 j
PS >.\program.exe 0& C( [- Z5 O* _) b
even% |+ Y. c C! V4 T1 f& Z$ g
PS >.\program.exe 10000007 K# \$ J8 A/ E$ i/ e4 i* c. i
even, X# e( o+ C% n0 e, ?2 |6 E
PS >.\program.exe 1000000075 U& |. O# W7 O/ B( ~4 M3 m
odd6 C' q' y- O7 e* n
PS >.\program.exe 400000000
" _! j! f' V' l7 }5 p$ M/ Zeven
0 v0 j/ h1 G9 k0 a8 s7 l' aPS >.\program.exe 400000001% a& n6 m- u% f: D$ n" m- B" v
odd
1 H( ]8 {5 o O/ ?, P; lPS >.\program.exe 400000006, W: F7 {/ K: d& `) n( W% E# ~8 F q
even8 s. S* h: P3 Y$ d' G9 _ d: x$ o, s
PS >.\program.exe 4200000000! \2 o! V L& n* R# @2 Z$ W
odd 差不多了!似乎算法在符号性方面有问题,任何超过 2^31 的值似乎都会给出随机结果。那么,让我们来修复最后一个错误:原来 atoi 不能处理无符号性,所以它无法解析大数字。用 strtoul 代替它就能解决所有问题。! f. z" \( x0 E2 c; x6 ?' g
uint32_t number = strtoul(argv[1], NULL, 10);// No problems here9 r" L4 A; t4 R, o9 o' k( y
PS >.\program.exe 4200000000
4 d% L6 s) b6 L' K, ieven* j" S9 v- ?8 `/ {7 L3 s
PS >.\program.exe 4200000001" M4 N$ l" U4 `7 r9 H9 z
odd顺便提一句,这个程序的性能很不错。对于小数字,结果能即时返回,而对于接近 2^32 极限的大数字,结果仍能在大约 10 秒内返回。考虑到计算机必须从磁盘读取 40GB 的数据,将其映射到物理内存,然后让 CPU 在没有缓存的情况下对其进行处理,老实说这个速度已经相当令人惊叹了。作为参考,我电脑的配置为 Core i5 12600K,32GB 内存,文件存储在 M.2 SSD 硬盘上。在计算过程中,我看到 SSD 硬盘的峰值读取速度约为 800 MB/s。
. A1 l4 q' P* Q9 O至此,互联网再次被证明是错误的:你不仅可以按照 TikTok 帖子的方式编写一个功能齐全、性能良好的程序,而且还非常有趣。0 i4 S3 E6 h5 S5 _% r. x
153x1nda3eq640106052332.png
# B& L: Q& @* N9 I/ m. i1 G! W) ?
网友:没必要,一个简单的 for 循环就能解决( [# l# n0 ]5 N0 ~# v2 [
不过 Andreas Karlsson 的分享,并没有得到部分开发者的认可,甚至认为他有些“哗众取宠”:
# c0 F6 x; m& K5 x4 q“在我看来,这几乎是过度设计。为什么要费尽心思生成代码?只需一个简单的‘for 循环’就能解决。”) B/ _0 \ }7 ?+ I, ^
func isOdd(n int) bool {
8 r6 O7 r u R) m& x var odd bool+ b* q$ x! f. {* C- W I0 I9 |! J' r
for i := 0; i return odd
& @3 V& w& U8 Z, W }" {% ] o. t. v1 w! K1 }+ T9 M4 A
0 x: y6 p- F b- s0 w e
“真正高质量的运行应始终使用递归。”! c1 s ^, Q) L7 J! T
func isOdd(n int) bool {3 o: C8 U* F/ x& ]. h7 }
switch {
# D- k4 b; E" U# A case n == 0: m6 A* i& k/ `+ [% {* @0 J
return false2 j5 ~3 _) l$ R: B
case n > 0:
9 g2 `# _4 Q: i+ l% T return !isOdd(n-1)" r3 j! y$ [ n6 n
default:
; k( [. U4 B8 S7 B) m; W( D1 | return !isOdd(n+1)
3 L' w6 B8 c) J+ G: K }5 c1 A6 l$ D$ T1 v
}
3 r8 q! z5 g& R9 Q# M M9 e还有人指出:“我完全听不懂这个笑话。我们从中学到了什么?exe 文件不能超过4GB?一个2^32 if 的程序大约是300GB?这看起来并不疯狂,只是毫无意义。”. u9 Y' M# X, H. k
对此,有人反驳道:“可笑的是,他真的做到了。几十年来,人们一直在拿它开玩笑,但这个人是认真的。由于代码多得太极端,没有编译器可以处理,甚至没有任何已知的汇编程序,因此他必须生成自己的机器码二进制文件才能运行。结果最后,他居然还真的成功了。”
7 I( V2 c! ~8 _& A- ?8 ^* d% d: k参考链接:
W5 ^, V, F2 i3 Jhttps://andreasjhkarlsson.github.io/jekyll/update/2023/12/27/4-billion-if-statements.html1 y! z- @) l: G2 Q
https://news.ycombinator.com/item?id=38790597. d, t, l& E8 _9 V F
使用函数指针可以帮助我们编写更加灵活和通用的代码,并提高代码的可重用性和可扩展性。0 x* D% M( t9 C; e: q; d
?版权声明:本文来源网络,免费传达知识,版权归原作者所有。如涉及作品版权问题,请联系我进行删除。——EOF——你好,我是飞宇,本硕均于某中流985 CS就读,先后于百度搜索以及字节跳动电商等部门担任Linux C/C++后端研发工程师。
) x8 F5 Q% x, u5 o7 u1 A/ o9 t最近跟朋友一起开发了一个新的网站:编程资源网,已经收录了不少资源(附赠下载地址),如果屏幕前的靓仔/女想要学习编程找不到合适资源的话,不妨来我们的网站看看,欢迎扫码下方二维码白嫖~
9 |8 h" S, K' T/ n1 K. v: p8 h2 e( T7 j; R" n
5540en5towj640106052434.gif
F; r8 J( i; P2 o/ J- D0 j0 A7 m( I- {! J
同时,我也是知乎博主@韩飞宇,日常分享C/C++、计算机学习经验、工作体会,欢迎点击此处查看我以前的学习笔记&经验&分享的资源。/ V! x- d& Q. [. }+ q2 |# Z1 J
我组建了一些社群一起交流,群里有大牛也有小白,如果你有意可以一起进群交流。. ~% K0 C9 e: |& a
mhzl0i1wv3o640106052534.png
* T& y L- g* r8 v+ {' P
欢迎你添加我的微信,我拉你进技术交流群。此外,我也会经常在微信上分享一些计算机学习经验以及工作体验,还有一些内推机会。
# J) M5 e9 I2 F9 A- R& K
1 h' N, a2 A: h
04h1jnkv4ir640106052634.png
$ O) a1 |! |( @5 Y4 x* X) A2 L加个微信,打开另一扇窗
, ~- _+ v- o+ L0 ?7 A2 Y; g/ p( O8 y
afrslusxa5q640106052734.gif
|
|