接說方法:
1.復制下面的公式到顯示校驗結果的單元格,
=IF(D2="","",(IF(MID("10X98765432",MOD(SUMPRODUCT(MID(D2,ROW(INDIRECT("1:17")),1)*2^(18-ROW(INDIRECT("1:17")))),11)+1,1)=MID(D2,18,18),"正確","錯誤")))
2.把公式中D2即黃色內容,改成身份證號碼所在的單元格。
原理:身份證最后一位是根據前面十七位數字碼,按照ISO 7064:1983.MOD 11-2校驗碼計算出來的檢驗碼。作為尾號的校驗碼,是由號碼編制單位按統一的公式計算出來的,如果某人的尾號是0-9,都不會出現X,但如果尾號是10,那么就得用X來代替,因為如果用10做尾號,那么此人的身份證就變成了19位,而19位的號碼違反了國家標準,并且我國的計算機應用系統也不承認19位的身份證號碼。Ⅹ是羅馬數字的10,用X來代替10,可以保證公民的身份證符合國家標準。
說起圓周率π,很多人就想到祖沖之老爺子的割圓術。
說實話,祖大人也挺無奈的,從我們小學就開始割圓,一直割到大學還在割。
但割圓術只適合手算,如何用電腦算π呢?
泰勒展開在科學計算中簡直有著匪夷所思的變態威力。
之前我有一篇文章泰勒為何要展開? 泰勒公式有什么神奇作用?介紹了什么是泰勒展開,它可以把復雜函數轉換成加減乘除,比如sinx:
之所以要展開,是因為通用計算機本質上只能計算加減乘除。
首先想到的思路就是,反三角函數,根據定義有:
那么,接下來的問題就是,
如何計算arctan(1)
有人說,直接調用C語言庫函數atan(double,double)不就行了。
確實,這可以完成計算,然而,這是一種令人不齒的開掛行為,就好像我問怎么跑完馬拉松,你說你開車一溜煙就跑完了一樣。
庫函數是別人寫好的,我們現在是思索如何實現計算,而不是考慮如何調用。
至此,我們只好請出祖傳配方,把arctan(x)進行泰勒展開:
然后,令x=1,得到:
格雷戈里-萊布尼茨公式
它被稱為萊布尼茨級數,也被稱為格雷戈里-萊布尼茨級數,用以紀念萊布尼茨同時代的天文學家兼數學家詹姆斯·格雷戈里。
看起來很吊是不是······
但是啊但是,還不夠吊,因為問題還沒完:
這個級數收斂極慢。
比如,算到+4/9,也就是前五項,結果僅為3.3396,誤差有0.2之多。
它要到算500000項之后,才會精確到小數點后五位:
就算電腦也算得太累了。
何況萊布尼茲(1646年7月1日-1716年11月14日)當年是沒有電腦的!
于是,人們嘗試改進,希望能快點計算。
英國數學家梅欽在1706年用上面的級數,發掘了一個可以快速收斂的公式:
配合上面arctan(x)泰勒展開,梅欽依據此公式(沒有電腦),把圓周率計算到小數點后一百多位。
英國數學家威廉·謝克斯花15年的時間以此計算到小數點后707位,不過在第528位時出錯,因此后面的都不正確了。
微微杯具就是了。
現代有了電腦,我們希望更快的收斂速度,因此科學家在尋找新的級數。
歷史總是留給吊人的,也總是會生產一些吊人的。
比如:
拉馬努金公式
這玩意被稱為拉馬努金公式,是印度科學家拉馬努金發明的。
第一位用拉馬努金公式計算π并取得進展的是比爾·高斯珀,他在1985年計算了小數點后一千七百萬位。
收斂再快一點?還有楚德諾夫斯基公式:
楚德諾夫斯基公式
楚德諾夫斯基兄弟于1989年算得π小數點后10億(10?)位,法布里斯·貝拉于2009年算得2.7千億(2.7×1012)位,亞歷山大·易和近藤滋在2011年算得一萬億(1013)位。
意不意外,驚不驚喜,
無不無聊······
一個騰訊筆試題
在刷題的時候看到了騰訊筆試題的這個問題
long a=(long)(((int *) 0) + 4);
printf("%ld \n",a);
請問輸出 a 的值是多少?
先解釋最后的強制類型轉換
賦值操作的本質是傳送數據,而數據類型則是告訴 CPU 數據傳送的數量是多少。
強制類型轉換,就是當傳輸的源數據和目的數據數量不一樣的時候,就需要告訴 CPU 如果數據太多的話哪些數據需要截斷。
如果數據不夠的話需要填充什么信息(是全 1 還是全 0 或者別的東西)。
解決這個面試問題核心就是一個指針的長度 等價于這段代碼
#include <stdio.h>
int main(void)
{
int *pa=NULL;
pa=pa + 4;
printf("%ld \n",pa);
return 0;
}
如果還是不太清除,直接調試看看地址值
類型分別為long、int *、int *
加一是移動的是一個 int 類型指針的大小,在 32 位系統中一個指針是 4 個字節,在 64 位系統中一個指針是 8 個字節。
隨著人們要求的不斷提升和硬件的飛速發展,64 位的系統基本上達到目前的普及。
如果你 64 位操作系統指針是 4 字節,不要奇怪,這是為了兼容 32 為設計的。
所以我們常常遇見不同位數的操作系統中不同值的問題,我們如果只是知道定義上的區別肯定是遠遠不夠的,我們就來探討一下區別。
我們一起來看下這幾個概念。
補充個概念:
在同一時間中處理二進制數的位數叫字長。
處理字長為 8 位數據的 CPU 叫 8 位 CPU,32 位 CPU 就是在同一時間內處理字長為 32 位的二進制數據,64 位的 CPU 就是在同一時間處理 64 位的二進制數據。
計算機在同一時間內處理的一組二進制數稱為一個計算機的“字”,而這組二進制數的位數就是字長。
適應不同的要求及協調運算精度和硬件造價間的關系,大多數計算機均支持變字長運算,即機內可實現半字長、全字長(或單字長)和雙倍字長運算。在其他指標相同時,字長越大計算機的處理數據的速度就越快。
cpu尋址
字長由微處理器(CPU)對外數據通路的數據總線條數決定。
內存的最小可尋址單位通常都是字節。也就是說一個指針地址值可對應內存中一個字節的空間。
尋址空間一般指的是 CPU 對于內存尋址的能力,也就是 CPU 最大能查找多大范圍的地址。
CPU 的尋址能力以字節為單位 (字節是最小可尋址單位),如 32 位尋址的 CPU 可以尋址 2^32=4G的地址,這就是為什么 32 位尋址的 CPU 最大能搭配 4G 內存的原因,再多的話 CPU 就找不到了。
這里 CPU 的尋址位數是由地址總線的位數決定,32 位 CPU 的尋址位數不一定是 32 位,因為 32 位 CPU 中 32 的意義為字長。
對于 32 位尋址的 CPU,其地址值為 32 位的二進制數,所以可以表示的最大地址為 2 的 32 次方(一個指針的值就是一個 32 位的二進制數,32 位對應 4 Byte。所以,指針的大小實際上是由 CPU 的尋址位數決定,而不是字長。
例如:
實際上:
實際不是這樣的,有這樣的結果是因為以上幾種情況,處理器當前運行模式的尋址位數是不一樣的。
cpu
如下:
Intel 32 位處理器 32 位運行模式,邏輯 尋址位數 32,指針也就是 32 位,8 位一個字節,即 4 個字節 Intel 32 位處理器 16 位虛擬機運行模式,邏輯尋址位數 16,指針也就是 16 位,即 2 個字節。
此編譯器非彼編譯器
編譯器是根據目標硬件(即 CPU)的特性將源程序編譯為可在該硬件上運行的目標文件。如果一個編譯器支持 32 位的CPU,那么它就可以將源程序編譯為可以在該 CPU 上運行的目標文件。
該源程序中指針大小也會被編譯器根據該 CPU 的尋址位數(如 32 位)編譯選擇為 4 字節。我們綜上可得指針大小是由當前 CPU 運行模式的尋址位數決定!
看完這個,我們是不是對于位數和指針有了更深刻的理解了呢?