Thích Python hơn C để lập trình thuật toán


16

Tôi đã nghiên cứu một chút về thuật toán và đã xem xét các trang web như SPOJ.pl TopCoder, v.v. Tôi đã thấy rằng các lập trình viên thường thích C hoặc C ++ cho hầu hết các cuộc thi lập trình thuật toán.

Bây giờ tôi đã gặp một số rắc rối gần đây. Tôi biết cả một chút về C và Python và khi cố gắng viết mã tôi dường như thích Python hơn C cho hầu hết các thuật toán. Mỗi lần tôi ngồi viết mã trong CI đều bỏ cuộc sau khoảng 15 phút vì tôi thấy nó quá cồng kềnh và có xu hướng chuyển sang trăn. Vượt qua ma trận Con trỏ và vân vân dường như vô ích lãng phí thời gian mà tôi thực sự có thể được sử dụng để suy nghĩ về chính thuật toán.

Bây giờ tôi đã biết và đã nghe từ rất nhiều người rằng C là một ngôn ngữ rất quan trọng và là bánh mì và bơ của rất nhiều lập trình viên ngoài kia.

Điều tôi muốn biết là liệu cách tiếp cận này của tôi có bất kỳ nhược điểm / hậu quả / Nhược điểm nào không, v.v.

Đây không phải là cuộc tranh luận giữa Python và C; Đây là một câu hỏi về cách thức thực hành cụ thể này thích trăn hơn C vì tính dễ sử dụng sẽ ảnh hưởng đến tôi hoặc bất kỳ nhà lập trình / máy tính nào khác trong thời gian dài.


Tôi muốn nghe từ những người đã sử dụng các ngôn ngữ này trong ngành / và để phát triển phần mềm / thư viện lớn, v.v.


chủ đề này sẽ không hoàn thành nếu không có liên kết đến cuộc thảo luận này lukeplant.me.uk/blog/posts/iêu
permeakra

11
@permeakra: Đó chỉ là một câu nói hay, về cơ bản nói rằng việc học Haskell và Python không giúp bạn giỏi ngôn ngữ khác vì những ngôn ngữ khác đó rất tệ.
Robert Harvey

Nó không chỉ là một lời ca tụng, vì nó chứa mô tả về cách Python và Haskell ảnh hưởng đến tâm trí người dùng của họ và nhiều bình luận của những người khác về chủ đề đó. Mặc dù vậy, nó không sử dụng c làm ngôn ngữ cấp thấp, nhưng ngôn ngữ cấp cao hơn một chút, nhưng ý tưởng là như nhau - người ta bắt đầu đưa ý tưởng từ ngôn ngữ khác sang ngôn ngữ mà anh ta hiện đang làm việc, làm cho mã không thành ngữ . Nó có thể là một điều tốt, nhưng ...
permeakra

1
Đây là sự đảm nhận của tôi: plus.google.com/101996847784434186165/posts/7941QuL69yP
Wayne Werner

Sẽ rất thú vị khi thấy một chút về lập trình phi thuật toán , bất kể điều này là gì.
SK-logic

Câu trả lời:


14

Theo kinh nghiệm của tôi, khi mọi người gặp khó khăn vượt quá các thuật toán mã hóa trong C, điều đó thường là do họ liên kết chặt chẽ việc quản lý cấu trúc dữ liệu của họ với thuật toán của họ thay vì tạo ra sự trừu tượng thích hợp. Ví dụ, thao tác thủ công các con trỏ danh sách được liên kết ở mọi nơi thay vì thực hiện push()và các pop()chức năng. Họ đã quá quen với việc cung cấp những thứ trừu tượng đó cho họ.

Trong khi vấn đề này rõ ràng hơn nhiều với sự trừu tượng ở mức độ thấp hơn, việc không nhận ra sự kết hợp chặt chẽ và tạo ra sự trừu tượng phù hợp là một vấn đề ở bất kỳ cấp độ nào. Thực hành các kỹ năng này trong C cho đến khi bạn có thể tạo ra một thuật toán trông sạch sẽ và dễ đọc sẽ chuyển sang bất kỳ ngôn ngữ nào bạn sử dụng.

Vấn đề khác mà tôi thỉnh thoảng thấy trong số các lập trình viên python là khó thích nghi với hiệu suất ở quy mô. Cấp, hiệu suất thường không phải là mối quan tâm chính, nhưng cách dễ nhất để thực hiện thuật toán cho cấu trúc dữ liệu tương đối nhỏ có thể khiến hệ thống của bạn bị đình trệ khi bạn làm việc với gigabyte hoặc nhiều dữ liệu hơn. Trở thành một lập trình viên giỏi C giúp bạn nhận thức rõ hơn về những vấn đề đó trong bất kỳ ngôn ngữ nào.

Bạn có thể học những kỹ năng đó trong các ngôn ngữ khác? Chắc chắn, nhưng C giúp bằng cách làm cho nó rõ ràng hơn rất nhiều khi bạn làm sai.

Điều đó đang được nói, tôi sử dụng python để lập trình thuật toán khi tôi có sự lựa chọn, mặc dù tôi rất thoải mái trong C. Python có các tính năng ngôn ngữ làm cho nó rất hay cho loại lập trình đó và sự khác biệt về hiệu suất thường không đáng kể. Tôi không thể nói lý do tại sao các lập trình viên khác biết cả hai sẽ chọn C. Tôi tưởng tượng rất nhiều người trong số họ làm điều đó chỉ đơn giản là để tách biệt khỏi đám đông.


1
"Họ đã quá quen với việc cung cấp những thứ trừu tượng đó cho họ." Có phải điều này cho rằng tôi đã học trăn trước C và do đó không thể thích nghi hoặc một cái gì đó dọc theo những dòng đó?
đánh bại

10

Các nhà nghiên cứu có mối quan tâm chính không phải là lập trình thích các ngôn ngữ cấp cao hơn như Python, bởi vì họ có thể mã hóa một giải pháp dễ dàng hơn bằng các ngôn ngữ đó hơn là, C. Python đặc biệt phù hợp với điều này bởi vì nó mang tính định hướng "nguyên mẫu" hơn "Bao gồm pin" và nó tích hợp với các thư viện số như NumPy và SciPy.

Nếu một nhà nghiên cứu cần hiệu suất tốt hơn, họ thường sẽ bàn giao thuật toán mà họ đã tạo trong Python cho Kỹ sư phần mềm, họ sẽ tìm cách tối ưu hóa nó (tối đa và bao gồm cả mã hóa lại trong C).


Vì vậy, về cơ bản các nhà nghiên cứu và Kỹ sư phần mềm có mối quan hệ Crafts-man thiết kế? Và việc sử dụng cả hai loại người trong ngành thì sao?
ffledgling

9
Tôi nghĩ điều đáng nói là việc mã hóa một thuật toán bằng Python và sau đó viết một triển khai tinh tế hơn trong C, là một kịch bản hoàn toàn chấp nhận được.
Robert Harvey

hoặc "mã hóa lại trong Cython"?
endolith

10

Hãy nhớ rằng SPOJ.pl, cuộc thi ACM và tất cả các cuộc thi tương tự đều tập trung vào việc tạo ra mã làm việc nhanh chóng sẽ bị loại bỏ ngay sau cuộc thi. TopCoder thực hiện điều này, nhưng ở một mức độ nhỏ hơn (mã ít nhất được tổ chức đúng ở cấp thiết kế OO).

Tuy nhiên, trong thế giới thực của lập trình, hầu hết mọi lối tắt mà bạn tham gia trong các cuộc thi lập trình thuật toán là một mô hình chống. Chỉ khi bạn ghi nhớ điều này, bạn mới có thể đưa ra bất kỳ loại so sánh nào. Hãy lấy ví dụ của bạn: chuyển một mảng nhiều chiều giữa các hàm khác nhau. Trong môi trường cạnh tranh, cách tiếp cận tốt nhất sẽ chỉ đơn giản là khai báo mảng toàn cầu để tiết kiệm thời gian tìm ra các chi tiết cuộc gọi phù hợp (ví dụ: tôi có nên vượt qua kích thước không, hoặc có thể xác định được không?). Trong lập trình thực tế, tôi làm ngược lại.

Vì vậy, đối với câu hỏi của bạn, có bất kỳ hậu quả phức tạp nào khi chọn Python trên C cho các thuật toán, tôi sẽ nói không. Nếu bạn chỉ quan tâm đến thuật toán, bạn sẽ làm điều tương tự trong Python và C. Thực hiện nó bằng ngôn ngữ chức năng có thể mang lại một số khác biệt, nhưng thuật toán vẫn giống nhau.

Hầu như điều duy nhất bạn có được khi thực hiện thuật toán trong C là kiểm soát nhiều hơn đối với việc thực thi và đảm bảo bạn chỉ sử dụng các tóm tắt cấp thấp hơn. Đây không phải là một điều nhỏ, vì trong Python phần lớn sự phức tạp bị ẩn đi. Nhưng nếu vấn đề không phải là nhỏ trong các bản tóm tắt cấp cao hơn, thì bạn chỉ có thể bị mất tốc độ thực thi và trong hầu hết các trường hợp, bạn không thực sự cố gắng tạo chương trình nhanh nhất có thể, bạn chỉ đơn giản là học .

Như đã đề xuất, bạn luôn có thể trao đổi triển khai Python với triển khai C nếu Python quá chậm. Nhưng điều này có thể xảy ra 2-3 lần trong một dự án lớn, vì vậy bắt đầu bằng C có thể là một sự lãng phí thời gian, trừ khi đó là ngôn ngữ bạn chọn (và bạn đã chỉ ra là không).


1
Nếu một người đang viết một ứng dụng chuyên sâu về toán thực sự, người ta gần như chắc chắn sẽ chọn C hoặc C ++ (không có thứ gọi là 'C / C ++') vì hiệu suất tăng rất lớn so với bất kỳ ngôn ngữ nào được giải thích. Tôi đã xem Topcoder vài năm trước và tôi nhớ rằng đã thấy rất nhiều C ++ bị rò rỉ bộ nhớ một cách bừa bãi, vì các cuộc thi không quan tâm đến các chi tiết nhỏ như rò rỉ. Tôi đã không ấn tượng.
Jim ở Texas

Chính xác quan điểm của tôi. Đó là một câu hỏi về các ưu tiên: topcoders không quan tâm đến rò rỉ bộ nhớ, vì dù sao hạt nhân sẽ dọn sạch chúng; họ không quan tâm đến các thực hành xấu cũng như chống mẫu, nếu họ tiết kiệm thời gian.
K.Steff

2
Đoạn cuối của bạn thể hiện quy tắc vàng: "làm cho nó hoạt động, sau đó làm cho nó nhanh".
Carson63000

9

Là thành viên lâu năm của TopCoder và là người dùng SPOJ không thường xuyên, tôi có thể nói với bạn rằng một lý do chính để thích C / C ++ hơn các ngôn ngữ khác trong các cuộc thi là tốc độ thô. Khi việc thực hiện chương trình của bạn được tính thời gian, có một áp lực rất lớn để chọn ngôn ngữ "nhanh nhất" mà bạn có thể nhận được, bởi vì nó mang lại cho bạn sự chậm chạp hơn trong việc mã hóa thuật toán của bạn. Sự tiến bộ của tôi trong TC đã chuyển từ Java sang C # sang C ++.

Tuy nhiên, tình huống này phổ biến hơn trong các cuộc thi so với phát triển hàng ngày: mặc dù việc viết mã tối ưu là rất quan trọng, nhưng tầm quan trọng tương đối của việc hoàn thành mã của bạn ngay khi bạn có thể và làm cho nó có thể duy trì được càng nhiều càng tốt. hàng trăm chu kỳ CPU. Nếu bạn cảm thấy thoải mái hơn khi mã hóa một cái gì đó trong Python, thì nó thường là một giải pháp ưa thích.

Hơn nữa, Python cung cấp các khả năng cấp cao không có sẵn trong C ++. Xây dựng chúng ra thường rất tốn kém, và đôi khi thậm chí là không thể (ví dụ, xem xét xây dựng mã phản chiếu hoặc tự sửa đổi mã trong C ++). Trong trường hợp như vậy, việc dựa vào ngôn ngữ cấp cao hơn cũng có thể là một giải pháp tối ưu.


Vì bạn là người dùng của TC và SPOJ. Là sự đánh đổi giữa thời gian và sự đơn giản rất lớn nếu chúng ta sử dụng python cho mã? Tức là có thể thực hiện gửi thành công bằng python nếu thuật toán tương tự có thể được gửi thành công bằng C? (Có, tôi biết nó sẽ / có thể khác nhau rất nhiều câu hỏi nhưng sẽ có một lợi thế trong hầu hết các trường hợp hoặc chỉ một số?)
ffledgling

@Ayos Tôi không thể nói cho Python vì tôi chưa bao giờ sử dụng nó trong ngữ cảnh của TC hoặc SPOJ, nhưng lợi thế của C ++ so với C # và Java đôi khi chỉ quan trọng và thậm chí sau đó nó không quá quan trọng. Tôi chỉ có thể nhớ một trường hợp khi một cổng đơn giản của thuật toán được mã hóa từ C ++ sang C # đã bị lỗi khi hết thời gian, nhưng nó đã ở trong phòng thực hành. Hầu hết thời gian, khám phá thuật toán chính xác là điều duy nhất tạo ra sự khác biệt giữa các lần gửi thành công và thất bại.
dasblinkenlight

1
Lưu ý rằng các ngôn ngữ được giải thích như Python, Ruby và Perl chạy chậm hơn nhiều lần so với các ngôn ngữ cấp cao được biên dịch như Java và C # (bản thân chúng chậm so với C). Cuối cùng, điều đó không thực sự quan trọng trừ khi bạn có kế hoạch làm việc với các tập dữ liệu đặc biệt lớn hoặc cần tốc độ thời gian thực.
KChaloux

5

Mỗi lần tôi ngồi viết mã trong CI đều bỏ cuộc sau khoảng 15 phút vì tôi thấy nó quá cồng kềnh và có xu hướng chuyển sang trăn.

Tăng năng suất này là lý do phổ biến mà các công việc C và C ++ đã giảm đáng kể.

Đây là một câu hỏi về cách thức thực hành cụ thể này thích trăn hơn C vì tính dễ sử dụng sẽ ảnh hưởng đến tôi hoặc bất kỳ nhà lập trình / máy tính nào khác trong thời gian dài.

Có hai phần cốt lõi này. Đầu tiên là lập trình đại số. Nó thực sự không quan trọng bạn sử dụng ngôn ngữ nào để diễn đạt thuật toán. Làm việc với chính thuật toán và điều chỉnh đúng vấn đề là những phần quan trọng, vì vậy không có vấn đề thực sự ở đó.

Phần thứ hai là tăng năng suất. Sử dụng những thứ giúp bạn làm việc hiệu quả hơn theo thời gian là một thói quen tốt và sẽ không có ích gì ngoài sự nghiệp của bạn. Có thể diễn đạt các thuật toán bằng các ngôn ngữ khác nhau là rất hữu ích, nhưng sự hữu ích đó nói nhiều hơn về những thành ngữ mà ngôn ngữ sử dụng không nhất thiết là những ngôn ngữ đó là gì.

Nói tóm lại, đừng lo lắng về điều đó . Những gì bạn sử dụng để diễn đạt thuật toán ít quan trọng hơn nhiều so với khả năng diễn đạt nó.


3
"Việc làm C và C ++ đã giảm đáng kể". Huh? Điều này dường như được đưa ra khỏi màu xanh, như tôi thấy xu hướng ngược lại. -1 cho đến khi bạn có thể nêu một nguồn cho tuyên bố đó.

3

Ưu điểm của việc sử dụng các ngôn ngữ cấp cao hơn như Python hoặc Ruby là (1) cú pháp của chúng rất gần với mã giả và (2) các thư viện chuẩn của chúng cung cấp các cấu trúc dữ liệu hữu ích ngoài hộp (khái niệm bao gồm pin mà @Robert đã đề cập). Vì vậy, nó hoàn toàn tốt để sử dụng chúng. Sử dụng bất cứ điều gì tối đa hóa năng suất của bạn, thay vì chọn một ngôn ngữ chỉ vì nó là chủ đạo hoặc "tuyệt vời".


Bạn có phải là một hipster hay cái gì đó? Đây là PBR của bạn. Tôi? Tôi thà được mát mẻ.
Thomas Eding

2

Những gì bạn sẽ bỏ lỡ khi lập trình bằng các ngôn ngữ cấp "cao hơn" so với C / C ++ là học cách máy tính hoạt động. Bạn sẽ không thể phát triển những thứ như hệ thống nhúng, hệ thống hoạt động và trình điều khiển phần cứng. Biết C cũng giúp khi học lắp ráp.

Ngoài ra, phần lớn tất cả các hệ thống quan trọng của nhiệm vụ vẫn được phát triển bằng C, do đó bạn không thể làm việc trong một số nhánh phần mềm (hàng không vũ trụ / ô tô / med-tech, v.v.) mà không biết.


Câu hỏi rõ ràng là về các thuật toán, không phải về các khía cạnh gần gũi với kim loại.
Konrad Rudolph

@KonradRudolph Tốt thôi, nhưng viết trình điều khiển phần cứng thường liên quan rất chặt chẽ đến các thuật toán. Ví dụ, khi viết trình điều khiển cho bộ chuyển đổi tương tự sang số, bạn sẽ phải phát triển các bộ lọc kỹ thuật số và có lẽ một số loại hàng đợi hoặc hệ thống ưu tiên. Và sau đó là một API trên đầu trình điều khiển của bạn. Nó rất giống với việc viết một "đối tượng" hoặc "kiểu dữ liệu trừu tượng".

@Lundin Cảm ơn bạn đã đề cập đến những bất lợi trong kịch bản thế giới thực.
ffledgling

1

Nếu một câu hỏi được đặt ra về 'Ký hiệu Big O' và bạn thử và đo nó, thì có thể khó thực hiện hơn trong Python trừ khi bạn biết nhiều hơn về cách python thực hiện mọi thứ, ví dụ như danh sách Python không phải là danh sách được liên kết ; Sắp xếp Pythons là TimSort; Rác Python thu thập vào những thời điểm nhất định ...

Tôi luôn thấy việc kết nối chương trình C với những gì có khả năng xảy ra trên bộ xử lý sẽ dễ dàng hơn, nhưng ngay cả ở đây, có bộ nhớ đệm bộ xử lý; cắt giảm thời gian của HĐH; Tối ưu hóa trình biên dịch vv có thể ảnh hưởng đến trực giác của tôi.

Tôi thấy việc viết và gỡ lỗi mã Python nhanh hơn vì vậy, khi được lựa chọn, tôi sẽ viết đầu tiên bằng Python tập trung vào việc lấy thứ gì đó hoạt động. Với chương trình Python đang hoạt động này, bạn có thể thường xuyên đưa nó vào một hệ thống lớn hơn và tìm ra không chỉ nó hoạt động mà còn nếu nó đủ nhanh hoặc ở khía cạnh nào thì nó chậm. Nhận một số dữ liệu hiệu suất thực sau đó sẽ giúp khi bạn tối ưu hóa tốc độ và cho phép bạn kiểm tra phiên bản Python dựa trên bất kỳ lần viết lại nào sau này trong Python hoặc C hoặc bất cứ điều gì.

Vì vậy, hạn chế của việc sử dụng Python là khó có thể thu được lợi ích của các thuật toán được viết để mong đợi một số trình biên dịch giống như C cho mô hình bộ xử lý. Hạn chế của việc sử dụng chỉ C là như bạn đã nói: Đó là một con lợn để viết và gỡ lỗi và cuối cùng bạn phải viết thư viện của riêng mình quá thường xuyên.

Tôi nghĩ rằng tốt nhất là sử dụng cả hai (và các ngôn ngữ khác), cho đến khi bạn cảm nhận được sự đánh đổi của họ. Bản thân tôi là một lập trình viên C giỏi nhưng bây giờ viết rất ít mã C gốc, mặc dù tôi vẫn phải đọc (và đôi khi gỡ lỗi) mã C trong công việc của mình. Mặc dù tôi thích Python, tôi biết và vẫn sử dụng Perl và Awk (và sed và grep và sort và Tcl và C và ...).


Tôi không đồng ý với đoạn đầu tiên. Python tập trung mạnh vào các cấu trúc dữ liệu và ghi lại rõ ràng cách thức thực hiện các cấu trúc dữ liệu được xác định trước. Tất nhiên, bộ sưu tập rác sẽ làm lệch thời gian chạy, nhưng nó sẽ hiếm khi làm lệch thứ tự big-O.
Konrad Rudolph

1

Tôi sẽ khuyên bạn nhìn vào Scala hoặc Clojure (nhưng sử dụng chú thích loại). Trong một số trường hợp chúng có thể nhanh như C, trong những trường hợp khác họ vẫn còn nhiều hơn nhanh hơn sau đó Ruby / Python, trong khi có rất consice và ký hiệu rõ ràng không giống như C ( IMHO ). Xem xét mã này so với mã C:

for (i <- 1 to 100; j <- 2 until 100;
     k <- 1 to 2; if i != j) {
     //...
}

Ngoài ra họ có chức năng kho vũ khí lập trình tương tự như Ruby / Python map, filter, reducevv mà không phải là nhanh như iterating hoặc đuôi đệ quy gọi, tuy nhiên nó vẫn là nhanh hơn nhiều sau đó các ngôn ngữ kịch bản hoàn toàn năng động.


1

Tôi muốn nghe từ những người đã sử dụng các ngôn ngữ này trong ngành / và để phát triển phần mềm / thư viện lớn, v.v.

Tôi đã làm việc trên một phần nhỏ của một thư viện C ++ lớn trong một vài năm và đã viết cả luận án cử nhân và thạc sĩ trong bối cảnh của thư viện này. Thư viện, tình cờ, là một thư viện cho các thuật toán tin sinh học và cấu trúc dữ liệu.

Thư viện được xây dựng trong C ++ vì C ++ gần như hoàn hảo cho các yêu cầu cụ thể của thư viện này và cho các thư viện thuật toán nói chung. Nếu tôi phát triển một thư viện thuật toán khác và sự lựa chọn ngôn ngữ là của tôi, tôi gần như chắc chắn sẽ chọn lại C ++.

Lý do không chỉ là hiệu năng mà còn là hệ thống loại mạnh mà trước hết mang đến cho bạn sự an toàn hơn về loại và thứ hai là cung cấp cho bạn khả năng để các loại tài liệu của bạn sử dụng thuật toán. Điều này có thể (theo kinh nghiệm của tôi) tăng cường đáng kể khả năng đọc và bảo trì.

Điều đó nói rằng, đối với các hình tượng trưng và câu đố thuật toán đơn giản, tôi hầu như luôn sử dụng Python (chủ yếu là vì có, nó đọc gần giống như mã giả), trừ khi tôi đặc biệt muốn thử cách giải quyết vấn đề tốt nhất trong C ++. Cho đến nay, tôi chưa giải quyết được nhiều vấn đề SPOJ hoặc TopCoder vì vậy tôi không biết liệu hiệu suất có thực sự quan trọng đến mức sử dụng ngôn ngữ nhanh là rất quan trọng.

Nhưng thông thường, điều quan trọng là phải đạt được thuật toán để vượt qua. Trong những trường hợp đó, Python hoạt động tốt. Ví dụ, đối với các sự cố Project Euler (không được tính thời gian, chỉ có giải pháp chính xác mới được tính), Python hoàn toàn phù hợp.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.