現(xiàn)在網(wǎng)絡(luò)上的編程課程一浪接著一浪饿序,什么少兒編程,成人編程管嬉,AI編程皂林,層出不窮。
比如朋友圈火過一陣的Python編程蚯撩,好像不學(xué)點(diǎn)Python都不要意思在職場(chǎng)混础倍。雖然現(xiàn)在都喜歡打著Python的旗號(hào)來吸引大家學(xué)編程,但是筆者想表達(dá)一個(gè)觀點(diǎn):
編程不僅僅是學(xué)習(xí)一門編程語言
可以從編程的發(fā)展來論證這個(gè)觀點(diǎn)胎挎,說到編程沟启,就要講到計(jì)算機(jī)。
編程與計(jì)算機(jī)
計(jì)算機(jī)的產(chǎn)生是用來解決數(shù)學(xué)問題犹菇,數(shù)學(xué)問題可以是邏輯問題也可以是計(jì)算問題德迹。
最早的電子計(jì)算機(jī)用于彈道計(jì)算。現(xiàn)在對(duì)電子計(jì)算機(jī)的定義是:利用數(shù)字電子技術(shù)揭芍,根據(jù)一系列指令指示并且自動(dòng)執(zhí)行任意算術(shù)或邏輯操作串行的設(shè)備胳搞。這個(gè)定義通俗的講,就是可以運(yùn)來解決一些數(shù)學(xué)問題称杨,比如求解二元一次方程肌毅,或者邏輯問題,比如你媽和你女朋友同時(shí)落水姑原,你會(huì)先救哪一個(gè)悬而。
電子計(jì)算機(jī)有四個(gè)主要部分:算術(shù)邏輯單元、控制電路页衙、存儲(chǔ)器和輸入輸出設(shè)備摊滔。目前算術(shù)邏輯單元和控制電路被集成到了一塊電路上,就是CPU店乐。CPU就是計(jì)算機(jī)實(shí)際執(zhí)行指令的地方艰躺,計(jì)算機(jī)的運(yùn)行過程大致可以描繪成先從存儲(chǔ)器中獲取指令和數(shù)據(jù),然后執(zhí)行指令眨八,存儲(chǔ)數(shù)據(jù)腺兴,再獲取下一條指令。這個(gè)過程被反復(fù)執(zhí)行廉侧,直至得到一個(gè)終止指令页响。
指令如同數(shù)據(jù)一樣在計(jì)算機(jī)內(nèi)部是以二進(jìn)制來表示的篓足,比如說,10110000就是一條Intel x86系列微處理器的拷貝指令代碼闰蚕。我們把一連串的指令叫做程序栈拖。
為了使計(jì)算機(jī)能夠理解人的意圖,我們就必須將需解決的問題的思路没陡、方法和手段通過計(jì)算機(jī)能夠理解的形式告訴計(jì)算機(jī)涩哟,使得計(jì)算機(jī)能夠根據(jù)人的指令一步一步去工作,完成某種特定的任務(wù)盼玄。這種人和計(jì)算體系之間交流的過程就是編程贴彼。
編程就是編寫完成某個(gè)特定任務(wù)的一連串指令。
現(xiàn)在我們使用的手機(jī)埃儿、筆記本器仗、平板其實(shí)都是電子計(jì)算機(jī),都擁有前面講的4個(gè)部分童番。
編程與編程語言
計(jì)算機(jī)能理解的語言叫做機(jī)器語言精钮,也叫指令。這些指令是以二進(jìn)制表示的妓盲,我們識(shí)別和操作比較困難杂拨,所以一開始發(fā)明了匯編語言,把二進(jìn)制的指令變成一些助記符悯衬,利用這些助記符來進(jìn)行指令的編寫弹沽。比如我們編寫一個(gè)輸入兩個(gè)數(shù),輸出兩個(gè)數(shù)相加結(jié)果的程序筋粗,我們先使用匯編語言來進(jìn)行編寫:
data1 segment
var db 6,0,6 dup(0),'$'
da1 db 2 dup(0),0ah,0dh,'$'
da2 db 2 dup(0),0ah,0dh,'$'
str1 db 'please input two variable!',0ah,0dh,'$'
data1 ends
code1 segment
assume ds:data1,cs:code1
start:
mov ax,data1; 初始化
mov ds,ax
mov dx,offset var; 輸入相加的數(shù)
mov ah,0ah
int 21h
mov si,2 ;把第一個(gè)數(shù)移動(dòng)到大da1
mov cx,2
lea di,da1
loopda1:mov bl,byte ptr var[si]
mov byte ptr [di],bl
inc si
inc di
loopnz loopda1
inc si
mov cx,2
lea di,da2
loopda2:mov bl,byte ptr var[si]
mov byte ptr [di],bl
inc di
inc si
loopnz loopda2
lea di,da1
lea si,da2
mov cx,2
loop1:sub byte ptr [di],30h
sub byte ptr [si],30h
inc di
inc si
loopnz loop1
dec si
dec di
clc
mov cx,2
mov bp,0
loop2:mov al,[di]
adc al,[si]
aaa
mov [di],al
dec di
dec si
loopnz loop2
inc di
mov cx,2
loop3:
add byte ptr[di],30h
inc di
loopnz loop3
mov [var+4],'+'
mov [var+7],'='
mov dx,offset var
add dx,2
mov ah,09h
int 21h
mov dx,offset da1
mov ah,09h
int 21h
mov ah,4ch
int 21h
code1 ends
end star
————————————————
版權(quán)聲明:本文為CSDN博主「loudyten」的原創(chuàng)文章策橘,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議,轉(zhuǎn)載請(qǐng)附上原文出處鏈接及本聲明娜亿。
原文鏈接:https://blog.csdn.net/loudyten/article/details/8222373
隱約能看到add這個(gè)單詞丽已,表示是相加操作,上面這一段指令包含了很多直接操作CPU的指令买决,基本上描述了計(jì)算機(jī)的整個(gè)運(yùn)行細(xì)節(jié)沛婴。但是人們覺得像這樣根據(jù)機(jī)器語言進(jìn)行編程,效率太低督赤,而且容易出錯(cuò)嘁灯。就希望能想平時(shí)說話寫字,解答數(shù)學(xué)題目一樣編程躲舌,有了這個(gè)目標(biāo)丑婿,很多編程語言就被發(fā)明了出來(相對(duì)于匯編語言,這些語言可以統(tǒng)稱為高級(jí)語言),比如C語言羹奉,用C語言實(shí)現(xiàn)兩個(gè)數(shù)相加
#include <stdio.h>
int main()
{
int a,b;
scanf("%d %d",&a, &b);
printf("%d\n",a+b);
return 0;
}
是不是比上面的匯編簡(jiǎn)單了不止10倍秒旋,但是用高級(jí)語言編寫的指令是沒法直接讓計(jì)算機(jī)理解了,這個(gè)時(shí)候需要一個(gè)翻譯诀拭,把高級(jí)語言翻譯成計(jì)算機(jī)能認(rèn)識(shí)的機(jī)器語言迁筛,計(jì)算機(jī)才能運(yùn)行。這就是每個(gè)高級(jí)語言都會(huì)帶一個(gè)自己的編譯器(C語言)或者是解析器(Python語言)炫加。編譯器和解析器都是用來將高級(jí)語言轉(zhuǎn)化為機(jī)器語言的瑰煎。
不同的任務(wù)可能需要不同的編程語言铺然,比如制作網(wǎng)頁結(jié)構(gòu)需要HTML俗孝,編寫安卓應(yīng)用需要Java等等。但是語言只是工具魄健,用工具的人才決定了產(chǎn)出的價(jià)值赋铝。
編程與應(yīng)用程序
我們平時(shí)使用手機(jī)、電腦沽瘦。其實(shí)是使用上面的應(yīng)用程序革骨,不管是打游戲,看視頻析恋,處理文檔良哲。我們都需要相應(yīng)的應(yīng)用程序,這些應(yīng)用程序提供了我們想要的功能或者信息助隧。而且這些應(yīng)用程序都充分使用了計(jì)算機(jī)的輸入輸出設(shè)備筑凫,讓我們可以和應(yīng)用程序提供的信息進(jìn)行交互。
要編寫一個(gè)完成特定任務(wù)的應(yīng)用程序并村,需要知道完成這個(gè)任務(wù)的每一步巍实,然后把每一步轉(zhuǎn)換成機(jī)器能理解的指令。這里簡(jiǎn)單來看有兩個(gè)步驟:做什么和如何做哩牍。做什么編程這件事關(guān)不了棚潦,但是如何做就是編程需要操心的。
解決同一個(gè)問題膝昆,可能有很多種方法丸边,編程的人首選需要找到解決這個(gè)問題的方法并且把它用某種編程語言進(jìn)行實(shí)現(xiàn)。然后就有了這個(gè)應(yīng)用程序荚孵。再抽象一點(diǎn)就是制定方案+實(shí)施方案妹窖。比如我們需要為編寫一個(gè)程序解決下面這個(gè)問題:
你正在安裝一個(gè)廣告牌,并希望它高度最大处窥。這塊廣告牌將有兩個(gè)鋼制支架嘱吗,兩邊各一個(gè)。每個(gè)鋼支架的高度必須相等。
你有一堆可以焊接在一起的鋼筋 rods谒麦。舉個(gè)例子俄讹,如果鋼筋的長度為 1、2 和 3绕德,則可以將它們焊接在一起形成長度為 6 的支架患膛。
返回廣告牌的最大可能安裝高度。如果沒法安裝廣告牌耻蛇,請(qǐng)返回 0踪蹬。
示例 1:
輸入:[1,2,3,6]
輸出:6
解釋:我們有兩個(gè)不相交的子集 {1,2,3} 和 {6},它們具有相同的和 sum = 6臣咖。
示例 2:輸入:[1,2,3,4,5,6]
輸出:10
解釋:我們有兩個(gè)不相交的子集 {2,3,5} 和 {4,6}跃捣,它們具有相同的和 sum = 10。
示例 3:輸入:[1,2]
輸出:0
解釋:沒法安裝廣告牌夺蛇,所以返回 0疚漆。提示:
0 <= rods.length <= 20
1 <= rods[i] <= 1000
鋼筋的長度總和最多為 5000來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/tallest-billboard
著作權(quán)歸領(lǐng)扣網(wǎng)絡(luò)所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系官方授權(quán)刁赦,非商業(yè)轉(zhuǎn)載請(qǐng)注明出處娶聘。
這個(gè)問題,數(shù)據(jù)大一點(diǎn)甚脉,人解決起來都很困難丸升,更別說編程了。這就需要能想到一個(gè)能使用計(jì)算機(jī)語言進(jìn)行表達(dá)的方案牺氨。一旦你想到了一個(gè)方案狡耻,使用什么編程語言來解決,就非常簡(jiǎn)單了波闹。
下面來看一下使用一個(gè)方案酝豪,但是兩種語言來實(shí)現(xiàn)的情況:
想法
對(duì)于每一根鋼筋 x,我們會(huì)寫下 +x精堕,-x 或者 0孵淘。我們的目標(biāo)是最終得到結(jié)果 0 并讓正數(shù)之和最大。我們記所有寫下的正數(shù)之和為 score歹篓。例如瘫证,+1 +2 +3 -6 的 score 為 6。
因?yàn)?sum(rods) 的大小限制庄撮,就說明可以利用這個(gè)性質(zhì)背捌。事實(shí)上,如果之前已經(jīng)寫下了一些數(shù)字洞斯,那么就不需要考慮這些數(shù)字是如何得到的毡庆。例如坑赡,rods = [1, 2, 2, 3],我們可以用 3 種方法得到和為 3么抗,但只考慮最終的 score 為 3毅否。數(shù)字之和的上界是 10001,因?yàn)橹挥?[-5000, 5000] 區(qū)間內(nèi)的整數(shù)是可能的值蝇刀。
算法
dp[i][s] 表示當(dāng)我們可以使用 rods[j] (j >= i) 時(shí)能得到的最大 score螟加,由于之前寫下的數(shù)字和為 s(不統(tǒng)計(jì)在 score 內(nèi))。例如吞琐,rods = [1, 2, 3, 6]捆探,可以有 dp[1][1] = 5,在寫下 1 之后站粟,可以寫下 +2 +3 -6 使得剩下的 rods[i:] 獲得 score 為 5黍图。
邊界情況:dp[rods.length][s] 是 0 當(dāng) s == 0,剩余情況為 -infinity 卒蘸。遞推式為 dp[i][s] = max(dp[i+1][s], dp[i+1][s-rods[i]], rods[i] + dp[i+1][s+rods[i]])雌隅。
作者:LeetCode
鏈接:https://leetcode-cn.com/problems/tallest-billboard/solution/zui-gao-de-yan-gao-pai-by-leetcode/
來源:力扣(LeetCode)
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán)缸沃,非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。
Java語言實(shí)現(xiàn)
class Solution {
int NINF = Integer.MIN_VALUE / 3;
Integer[][] memo;
public int tallestBillboard(int[] rods) {
int N = rods.length;
// "memo[n][x]" will be stored at memo[n][5000+x]
// Using Integer for default value null
memo = new Integer[N][10001];
return (int) dp(rods, 0, 5000);
}
public int dp(int[] rods, int i, int s) {
if (i == rods.length) {
return s == 5000 ? 0 : NINF;
} else if (memo[i][s] != null) {
return memo[i][s];
} else {
int ans = dp(rods, i+1, s);
ans = Math.max(ans, dp(rods, i+1, s-rods[i]));
ans = Math.max(ans, rods[i] + dp(rods, i+1, s+rods[i]));
memo[i][s] = ans;
return ans;
}
}
}
作者:LeetCode
鏈接:https://leetcode-cn.com/problems/tallest-billboard/solution/zui-gao-de-yan-gao-pai-by-leetcode/
來源:力扣(LeetCode)
著作權(quán)歸作者所有修械。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán)趾牧,非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。
Python語言實(shí)現(xiàn)
from functools import lru_cache
class Solution:
def tallestBillboard(self, rods):
@lru_cache(None)
def dp(i, s):
if i == len(rods):
return 0 if s == 0 else float('-inf')
return max(dp(i + 1, s),
dp(i + 1, s - rods[i]),
dp(i + 1, s + rods[i]) + rods[i])
return dp(0, 0)
作者:LeetCode
鏈接:https://leetcode-cn.com/problems/tallest-billboard/solution/zui-gao-de-yan-gao-pai-by-leetcode/
來源:力扣(LeetCode)
著作權(quán)歸作者所有肯污。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán)翘单,非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。
通過這個(gè)問題蹦渣,想說明的是哄芜,編程包括了兩個(gè)步驟:實(shí)現(xiàn)方案和把實(shí)現(xiàn)方用編程語言表達(dá)出來。
上面這個(gè)例子雖然是解決一個(gè)算術(shù)問題柬唯,但是到開發(fā)一個(gè)實(shí)際的應(yīng)用程序原理是一樣的认臊。
編程與電影
如果把編程比作拍電影,那么劇本就相當(dāng)于實(shí)現(xiàn)方案锄奢,拍攝器材相當(dāng)于編程語言失晴,演員相當(dāng)于使用的開發(fā)技術(shù),比如框架拘央,第三方類庫等(不是從頭開始培養(yǎng)演員涂屁,而是有很多現(xiàn)成的演員可以拍這個(gè)電影),導(dǎo)演就是編程的人灰伟。
要是這樣類比就能理解拆又,會(huì)使用拍攝器材就能拍出小視頻,能請(qǐng)到明星,拍出的東西肯定有流量帖族,如果劇本好义矛,群眾演員也能拍出好的電影。但是同一個(gè)故事盟萨,不同的導(dǎo)演往往能拍出不同的水平凉翻,這其中的奧秘不是器材、演員和劇本能決定的捻激。
從學(xué)好拍電影的角度講制轰,學(xué)習(xí)編程你可能需要知道如何使用開發(fā)技術(shù),如何選取適當(dāng)?shù)木幊陶Z言胞谭,理清楚實(shí)現(xiàn)方案(可以從最簡(jiǎn)單的兩個(gè)數(shù)相加問題開始)然后不斷拍小視頻檢驗(yàn)自己的作品垃杖,能否算的上是一個(gè)好的短片(程序)。
所以編程其實(shí)不僅僅是學(xué)一門編程語言那么簡(jiǎn)單丈屹,語言只是解決了拍攝問題调俘,能幫你處理遠(yuǎn)景,人物旺垒,調(diào)色等等問題彩库,但是要拍什么,拍成什么樣先蒋,表達(dá)什么核心觀點(diǎn)骇钦,才是導(dǎo)演重點(diǎn)思考的問題,不然可能只是一名優(yōu)秀的攝像師竞漾。
歡迎大家討論眯搭。