跳轉到內容

程式設計科學/常數問題

來自華夏公益教科書,開放書籍,開放世界

到目前為止,我們的多項式只包含一個單項式,例如

 

這很限制。例如,一條直線的方程

 

可以看作是一個多項式,其項具有一個冪,加上一個常數項,b。換句話說

 

我們如何處理常數項?我們可以修改我們的term建構函式,使其接受第三個引數,一個常數項。在這種情況下,我們將直線模型化為

 

 term(3,1,-5)

雖然這會奏效,但當我們開始對由多個項組成的多項式建模時,這種方法會使事情變得複雜。考慮

 

這個多項式可以用以下項表示

 term(4,4,0)
 term(-2,3,0)
 term(5,2,0)
 term(1,1,-3)

其中前三個項的常數項為零。或者,我們可以用這種方式表示多項式

 term(4,4,1)
 term(-2,3,2)
 term(5,2,3)
 term(1,1,-9)

現在每個項都有一個常數項(注意所有常數項加起來為 -3,如預期的那樣)。現在你應該看到給term新增第三個引數的兩個問題。第一個問題是大多數項沒有(或不應該有)常數項。第二個問題是不清楚在一個項集合中,哪個項應該包含常數項。

在我告訴你更好的方法之前,先給你講個故事。我有一個朋友,他的兄弟(或表兄弟或其他,我不記得了),因為沒有撬棍,就用一把克萊斯勒螺絲刀把一個相當重,而且卡得很緊的機械零件從它的外殼中撬出來。這個零件紋絲不動,於是他的兄弟(或表兄弟或其他)把全身的重量都壓在了螺絲刀上,螺絲刀立刻彎了。你現在可能不知道,彎了的螺絲刀幾乎不能做螺絲刀通常做的事情(比如擰緊或鬆開螺絲)。恰好克萊斯勒手工具有終身保修,所以他的兄弟(或表兄弟或其他)帶著彎了的螺絲刀回到了西爾斯,要求更換。店員很高興地拿了一把新的螺絲刀,並一邊換螺絲刀,一邊說:“你知道,西爾斯也賣克萊斯勒撬棍。”

這個故事的寓意是什麼?當然,它就是用合適的工具做合適的事情[1]我們需要一個新的工具來表示常數項。

常數物件

[編輯 | 編輯原始碼]

你可能在問,常數項到底有什麼大不了的?為什麼我們不能直接用數字?我們可以,但考慮一下這段對話

  sway> var s = t . diff();
  OBJECT: <OBJECT 4369>

假設t繫結到一個term物件。那麼一切都很順利;s也繫結到一個term物件。但假設t繫結到數字八。我們從終端得到一個更糟糕的響應

 sway> var s = t . diff();
 EVALUATION ERROR: :accessError
 dot operator used on type INTEGER

我們試圖將數字八當作一個物件來處理,而它不是一個物件。由於數字是有效的數學實體,並且對數字求微分是有意義的,我們剩下兩個選擇

  1. 每次我們想求微分或找一個值或視覺化時,都需要測試我們正在處理的實體是否是一個物件。
  2. 確保數字是具有diffvaluetoString方法的物件。

第一個選擇意味著我們將來編寫的每一行程式碼都必須考慮到我們有兩種型別的實體,我們最好不要忘記這一點。

第二個選擇意味著在開始時花一點時間,但以後就再也不用擔心多種型別的實體了。

很明顯,第二個選擇是我們要走的路。在我們編寫表示常數的建構函式之前,我們需要問問自己三個問題

  • 在特定點,常數項的值是多少?
  • 常數項的導數是多少?
  • 常數項的合理字串表示是什麼?

這三個問題對應於所有建構函式必須具有的三種方法。

其中第一個問題似乎有點奇怪。term的值函式計算了給定x的值時,term的值。當x變化時,term的值也會變化。但對於常數項,似乎不存在x。這不是完全正確的,因為存在一個方程,其中y的值保持不變,無論x的值是多少。一個例子是方程

 
 

我們可以繪製該方程

 File:Ch05-figure01.png

我們看到,無論x的值是多少,y的值都保持不變。因此,常數物件的value方法應該忽略給定的x的值,並返回其常數值

 function constant(n)
   {
   function value(x)
     {
     n;
     }
   this;
   }

注意,value方法始終返回n

 sway> var c = constant(5);
 sway> c . value(0);
 INTEGER: 5
 sway> c . value(3);
 INTEGER: 5

接下來,常數項的微分是多少?換句話說,當x的值發生變化時,我們的物件的值如何變化。我們從上面的互動中看到,值根本沒有變化。換句話說,變化為零。因此,你可能會傾向於將常數物件的diff方法寫成

 function diff()
   {
   0;    //incorrect
   }

然而,這將是不正確的,因為所有diff方法都必須返回本身具有diff方法的物件。我們在terms中看到了這一點:term物件的diff方法返回一個term物件,該物件具有一個diff方法,如預期的那樣。對於手頭的任務,應該用什麼物件來表示數字零?一個常數物件!

 function constant(n)
   {
   function value(x)
     {
     n;
     }
   function diff()
     {
     constant(0);
     }
   this;
   }

我們最後一個要回答的問題是如何視覺化一個常數項?這很容易回答:我們只需將數字轉換為字串。我們得到了完整的常數建構函式

 function constant(n)
   {
   function value(x)
     {
     n;
     }
   function diff()
     {
     constant(0);
     }
   function toString()
     {
     "" + n;
     }
   this;
   }

使用常數物件

[編輯 | 編輯原始碼]

真是一個大的偏差!記住,我們試圖用term和常數項來模擬一條直線。直線

 

可以用兩個物件表示

 term(m,1)
 constant(b)

當我們將它們加在一起時會發生什麼?

 sway> var m = 3;
 sway> var b = -5;
 
 sway> term(m,1) + constant(b);
 EVALUATION ERROR: :argumentTypeError
 addition: cannot add type OBJECT to type OBJECT

現在我們需要一種方法將這兩個物件粘合在一起。清楚地讓我們測試一下。回想一下我們的term建構函式

 function term(a,n)
   {
   function value(x)
     {
     a * (x ^ n);
     }
   this;
   }
 

讓我們建立一個值為 7 的常數項,看看term的最終值是否確實與x的值無關。

 var c = term(7,0);
   
 sway> c . value(10);
 INTEGER: 7
 sway> c . value(1000);
 INTEGER: 7

確認。

所有公式都使用小學優先順序編寫。

1. 使用 Sway 來表示以下多項式的各個項 . 當 時,這個多項式的值是多少?

2. 使用 Sway 來表示以下多項式的各個項 . 當 時,這個多項式的值是多少?

3. 嬰兒死亡率與收入水平成反比。嬰兒死亡率相對於收入水平的增長率是多少?

  1. 有時,計算機科學家會忽略這條規則,他們更喜歡另一個故事的寓意:下次用一把更大的螺絲刀。這是因為計算機科學家(又一次懶惰)不想從頭開始寫東西(一個撬棍),而是更願意使用其他已經寫好並且可以適應手頭工作的工具(螺絲刀)。有時,這很好用,但有時會導致將來出現額外的複雜情況。在這種情況下,一個常數c可以用係數為c,指數為零的term來表示。相反,我們將設計我們微積分系統中的第二種物件。


最簡單的事情 · Guzzintas和其他計算方法

華夏公益教科書