讓特斯拉再飛一會兒,GM 不介意在電動車市場落後

特斯拉無疑是目前電動車領域的領先者,從電池、馬達到控制元件都比各大車廠先進,然而通用汽車並不擔心,儘管特斯拉在 2019 年賣出破紀錄的 37 萬輛車,仍然離通用的 290 萬輛非常遙遠。

上個月才宣布經典悍馬車電動化的消息,通用汽車(GM)手上還有越賣越賠錢的 Chevy Bolt,這兩款電動車從價格與性能來看,都不是特斯拉的對手,事實上目前市面大部分電動車都不是,但為什麼這些大車廠似乎不太擔心?

「我們預估今年車市會持續低迷,美國市場約會下滑 50 萬輛」,GM 財務長迪瓦‧蘇里亞帝娃拉(Dhivya Suryadevara)預估,中國跟南美洲也同樣會繼續衰退。

一片悲觀中,特斯拉一枝獨秀的股價讓 GM 看起來毫無抵抗之力,不過這些老車廠可不像股價看起來這麼脆弱。

特斯拉去年創下銷售新高紀錄,總共售出約 37 萬輛電動車,但虧損 8.25 億美元(第三、第四季為正);通用汽車則賣出 290 萬輛車,利潤 67 億美元。市場雖然寵愛特斯拉,但當這些大廠開始砸錢時,規模非常驚人。

GM 最近陸續宣布要改建底特律廠,當作電動車與自駕車專用產線;同時還與南韓 LG Chem 合作興建新電池廠,總共投入 45 億美元,但什麼時候要真的把錢砸下去,還在看正確的時間點。

電動車的獲利關鍵:電池成本

「對 GM 來說,不介意在市場讓特斯拉領先,之後再砸大錢追上它。」彭博汽車產業分析師 Kevin Tynan 認為,當電動車真正能獲利時,GM 隨時都能衝出大量產能並快速生產。

隨著政府補貼逐漸縮水或退場,特斯拉的高價車款銷量大幅下滑,而在市場快速成長的 Model 3 最終也只在去年幫特斯拉多賺了 0.3% 營收。

電動車要能賺錢,關鍵還是回到製造成本,尤其是電池成本,想要降低成本就必須靠技術突破,然而特斯拉已經在 2019 第三季開始放慢資本支出的速度,以彌補前兩季的虧損,整個 2019 年資本支出跟前一年幾乎相同,因此才能在上一季交出漂亮財報,同時帶動股價一飛沖天。

反觀通用汽車,即使去年遭遇勞資問題,導致 36 億美元損失,全年獲利還是高達 67 億美元,面對萎縮的全球車市,GM 還是預估休旅車跟皮卡車能維持不錯獲利,而這些收入都將持續投入電池與電動車技術開發。

GM 電池工程總監 Tim Grewe 認為,要開發擁有價格效益的電池,還需要更先進的科技,而這些科技如今都還沒實現。在那之前,特斯拉將會持續稱霸電動車銷售市場,並繼續虧損。

最近特斯拉除了推進自行研發電池的進度,也在研討與寧德時代合作無鈷電池,以降低電池成本。這場電動車電池的爭戰,GM 決定讓特斯拉再飛一會,但會不會一不小心,就飛到再也追不到的地方了?

(合作媒體:。首圖來源:)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

南投搬家前需注意的眉眉角角,別等搬了再說!

高性能Web動畫和渲染原理系列(4)“Compositor-Pipeline演講PPT”學習摘要

目錄

示例代碼託管在:

博客園地址:

華為雲社區地址:

附件PPT來自開發文檔。術語里的cc指的是Chromium Compositor

一直以來都想了解瀏覽器合成層的運作機制,但是相關的中文資料大多比較關注框架和開發技術,這方面的資料實在是太少了,後來在chromium官方網站的文檔里找到了項目組成員malaykeshav在 2019年4月的一份關於瀏覽器合成流水線的演講PPT,個人感覺裏面講的非常清楚了,由於沒有找到視頻,有些部分只能自行理解,本文僅對關鍵信息做一些筆記,對此感興趣的讀者可以在文章開頭的github倉庫或附件中拿到這個PPT自行學習。

摘要

1.合成流水線

合成流水線,就是指瀏覽器處理合成層的工作流程,其基本步驟如下:

大致的流程就是說Paint環節會生成一個列表,列表裡登記了頁面元素的繪製指令,接着這個列表需要經過Raster光柵化處理,並在合成幀中處理紋理,最後的Draw環節才是將這些紋理圖展示在瀏覽器內容區。

2. 預定義UI層

chromium中預定義了一些指定類型的UI層,大致分為:

  • Not Drawn – 為了處理透明度或濾鏡效果、transform變形或者clip剪裁的非繪製層
  • Solid color layer – 固有顏色層
  • Painted texture layer – Texture紋理會在這個層執行paint渲染和後續的rasterized光柵化任務
  • Transferable resource layer – 共享資源層,可能是GPU裏面的Texture紋理也可能未來會發給GPU的位圖
  • Surface layer – 臨時佔位層,因為自頂向下遍歷layer樹時子樹都還沒處理,需要先佔位最後再填充
  • Nine patch layer – 用於實現陰影的層

3. paint是什麼意思

每個層layer是由若干個views組成的,所謂paint,就是每個views將自己對應圖形的繪製指令添加到層的可展示元素列表Display Item List里,這個列表會被添加到一個延遲執行的光柵化任務中,並最終生成當前層的texture紋理(可以理解為當前層的繪製結果),考慮到傳輸性能以及未來增量更新的需求,光柵化的結果會以tiles瓦片形式保存。在chrome中也可以看到頁面瓦片化拆分的結果:

4. 分層的優勢和劣勢

分層的優勢和劣勢也在此進行了說明,和之前我們主動思考的答案基本一致(暗爽一下)。

5. 視圖屬性及其處理方式

views中支持的屬性包含Clip剪裁,transform變換,effect效果(如半透明或濾鏡等),mask遮罩,通常按照後序遍歷的方式自底向上進行遍歷處理。

clip剪裁的處理方式是在父節點和子節點之間插入一個剪裁層,用來將其子樹的渲染結果剪裁到限定的範圍內,然後再向上與父級進行合併;

transform變換直接作用於父節點,處理到這個節點時其子樹都已經處理完畢,直接將整體應用變形即可;

effect效果一般直接作用於當前處理的節點,有時也會產生交叉依賴的場景;

PPT第40頁中在介紹effect效果處理時描述了兩種不同的透明度處理需求,從而引出了一個Render Surface的概念,它相當於一個臨時的層,它的子樹需要先繪製在這個層上,然後再向上與父節點進行合併,屏幕就是是根級的Render Surface

6. Quads

Layer遍歷處理輸出的結果被稱為Quads(從意思上理解好像就是指輸出了很多個矩形方塊),每個quad都持有它被繪製到目標緩衝區所需要的資源,根據它持有的資源不同可以分為:

  • Solid Color-固定顏色型
  • Texture– 紋理型
  • Tile– 瓦片型
  • Surface– 臨時繪圖表面型
  • Video – 視頻幀型
  • Render PassRender Surface類型的佔位區,Render Surface子樹處理完后填充到關聯的Render Pass

7. Compositor Frame

合成層真正的工作要開始了,主角概念Compositor Frame(合成幀)登場,它負責將quads合併繪製在一起,膠片里59-62頁非常清楚地展示了合成的過程,最終輸出的結果就是根節點的紋理。

chromium是多進程架構,Browser Process瀏覽器進程會對菜單欄等等容器部分的畫面生成合成幀來輸出,每個網頁的Render Process渲染進程會對頁面內容生成合成幀來輸出,最終的結果都被共享給GPU ProcessGPU進程進行聚合併生成最終完整的合成表面,接着在Display Compositor環節將最後的位圖展示在屏幕上。

8. 關於光柵化以及渲染方式

膠片里並沒有描述具體的光柵化的處理過程,但是layer輸出的quads看起來應該是光柵化以後的結果,推測應該是處理Display Item List中的繪圖指令時也和WebGL類似,經過頂點着色器片元着色器的遍歷式處理機制,並在過程中自動完成像素插值。

9.【重要】軟件渲染和硬件渲染的區別

聲明:本節內容是個人理解,僅用作技術交流,不保證對!

軟件渲染和硬件渲染的區別對筆者而言一直非常抽象,只是知道基本概念。後來在(國內可能無法訪問)中《Compositor Thread Architecture》這篇合成器線程架構的文章中找到了一些相關描述,也解開了筆者心中一直以來的疑惑,相關部分摘抄如下:

Texture Upload

One challenge with all these textures is that we rasterize them on the main thread of the renderer process, but need to actually get them into the GPU memory. This requires handing information about these textures (and their contents) to the impl thread, then to the GPU process, and once there, into the GL/D3D driver. Done naively, this causes us to copy a single texture over and over again, something we definitely don’t want to do.

We have two tricks that we use right now to make this a bit faster. To understand them, an aside on “painting” versus “rasterization.”

  • Painting is the word we use for telling webkit to dump a part of its RenderObject tree to a GraphicsContext. We can pass the painting routine a GraphicsContext implementation that executes the commands as it receives them, or we can pass it a recording context that simply writes down the commands as it receives them.
  • Rasterization is the word we use for actually executing graphics context commands. We typically execute the rasterization commands with the CPU (software rendering) but could also execute them directly with the GPU using Ganesh.
  • Upload: this is us actually taking the contents of a rasterized bitmap in main memory and sending it to the GPU as a texture.With these definitions in mind, we deal with texture upload with the following tricks:
  • Per-tile painting: we pass WebKit paint a recording context that simply records the GraphicsContext operations into an SkPicture data structure. We can then rasterize several texture tiles from that one picture.
  • SHM upload: instead of rasterizing into a void* from the renderer heap, we allocate a shared memory buffer and upload into that instead. The GPU process then issues its glTex* operations using that shared memory, avoiding one texture copy.The holy grail of texture upload is “zero copy” upload. With such a scheme, we manage to get a raw pointer inside the renderer process’ sandbox to GPU memory, which we software-rasterize directly into. We can’t yet do this anywhere, but it is something we fantasize about.

大概翻譯一下,方便英語水平一般的小夥伴理解,GPU處理圖片的方式是按照Texture進行貼圖的,對此不熟悉的小夥伴可以查看筆者以前發的有關Three.js相關的博文。

紋理上傳:
處理紋理的挑戰之一就是它是在渲染進程(可以理解為單個Tab網頁的進程)的主線程里進行的,但是最終需要將其放入GPU內存。這就需要將紋理數據遞交給合成器線程,然後再交給GPU進程(Chromium架構里有專門的GPU進程用來專門處理和GPU之間的協作任務),最後再傳遞給底層的Direct3DOpenGL(也就是圖形學的底層技術),如果只是按照常規流程來處理,就會需要一次又一次來複制生成的紋理數據,這顯然不是我們想要的。
我們現在使用了兩個小方法來使這個流程變得快一點。它們分別作用於painting(繪製)和rasterization(光柵化)兩個階段。

  • 1號知識點!!!Painting我們用來告訴webkit為RenderObject Tree的來生成對應的GraphicsContext。通過給painting routine(繪製流程)傳遞一個GraphicsContext的具體實現來執行這些已經編排好的繪製命令,也可以傳遞一個record context(記錄上下文)只是簡單地把繪圖命令都記錄下來。
  • 2號知識點!!!Rasterization(光柵化)是指Graphics context關聯的繪圖命令實際被執行的過程。通常我們使用CPU(也就是軟件渲染的方式)來執行光柵化任務,也可以直接使用GPU來渲染(也就是硬件渲染的方式)。
  • 上傳:指在主線程存儲區獲取到光柵化以後的位圖內容然後將它作為紋理上傳給GPU的過程,考慮到上述已經提及的定義,上傳過程是如下來處理的:
    • 瓦片繪製:我們在webkit中使用recording context來簡單地記錄Graphics Context的操作指令,將它存儲為SkPicture類型(直接使用軟件光柵化時生成的是SkBitmap類型),隨後可以從一張picture裏面光柵化處理得到多個紋理瓦片
    • 共享內存:在軟件渲染的方式中,光柵化的結果會被存儲在renderer進程的堆內存里,現在不這樣搞了,我們重新分配了一塊共享緩衝區,然後通過它來傳遞相關對象,GPU進程隨後在獲取紋理時直接從共享內存中獲取就行了,這樣就避免了數據的拷貝。
      總的來說,紋理上傳的過程幾乎是零拷貝的。利用這樣的結構,我們在renderer進程(也就是網頁的渲染進程)的沙箱環境內也可以獲取到指向GPU 內存的指針,而在軟件光柵化的過程中,是直接將位圖結果放在這裏的。
  • Painting: this is the process of asking Layers for their content. This is where we ask webkit to tell us what is on a layer. We might then rasterize that content into a bitmap using software, or we might do something fancier. Painting is a main thread operation.
  • Drawing: this is the process of taking the layer tree and smashing it together with OpenGL onto the screen. Drawing is an impl-thread operation.
  • painting:表示的過程是向Layers對象查詢層內容,也就是讓webkit告訴我們每一層上面到底有什麼。接下來我們就可以使用軟件光柵化的方式將這些內容處理為位圖,也可以做一些更牛的事情,painting是一個主線程行為。
  • drawing:是指將Layer中的內容用OpenGL繪製在屏幕上的過程,它是另一個線程中的操作。

概念比較多沒有基礎的讀者可能理解起來有難度,我嘗試用自己的話複述一下:

【軟件渲染】的模式下,在paint時會直接利用Graphics Context繪圖上下文將結果繪製出來,在一個SkBitmap實例中保存為位圖信息;【硬件渲染】的模式下,在paint時傳入一個SkPicture實例,將需要執行的繪圖命令保存在裏面先不執行,然後通過共享內存將它傳給GPU進程,藉助GPU來最終去執行繪圖命令,生成多個瓦片化的位圖紋理結果(OpenGL中頂點着色器向片元着色器傳遞數據時可以自動進行數據插值,完成光柵化的任務)。 純軟件渲染里嚴格說是沒有合成層概念的,因為最終輸出的只有一張位圖,按照順序從下往上畫,和畫到一個新層上再把新層貼到已有結果上其實是一樣的。

不管使用哪種途徑,paint動作都是得到位圖數據,而最終的draw這個動作是藉助OpenGL和位圖數據最終把圖形显示在显示器上。

所以【硬件渲染】就是渲染進程把要做的事情和需要的數據都寫好,然後打包遞給GPU讓它去幹活。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家費用,距離,噸數怎麼算?達人教你簡易估價知識!

奧迪展開純電動車電池量產

德國奧迪母公司德國福斯爆出柴油車廢氣檢驗造假爭議後,宣布將加強生產純電動車的方針。20日,奧迪汽車宣布將在比利時布魯塞爾工廠開始量產純電動SUV汽車以及車用電池,建立電動車一條龍生產線。

日經新聞報導,奧迪在2015年9月推出純電動SUV概念車,並規劃2018年開始在歐洲銷售的計畫。這款純電動SUV的行駛距離可達500公里,且奧迪也預計將向各公司供應電池以降低電池成本,並加速純電動車問世、普及的腳步。

在布魯塞爾電池廠開始量產後,奧迪將可建立電動車一條龍產線,強化自己的電動車市場競爭力。而同一工廠也將納入歐洲區的小型車生產體制重組規劃,將原先在該工廠生產的奧迪A1轉移到西班牙廠生產,原先在西班牙廠生產的小型SUV「Q3」則將轉至匈牙利生產。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家費用,距離,噸數怎麼算?達人教你簡易估價知識!

電動車將造成下個石油崩跌危機:BNEF

電動車目前佔車市的市佔仍然相當低,油國與石油業界對電動車也一向相當輕視,各項預測與未來石油產銷報告中往往都認為電動車的影響可略,不過,彭博新能源財經(Bloomberg New Energy Finance)的看法與他們相左,預言電動車將大行其道,而造成下一次油價崩跌危機。   目前電動車與充電式油電混合車只佔全球車市的 0.1%,在多數國家中都相當少見,而且車價也遠比汽油車高,油國組織(OPEC)十分輕視電動車的發展,認為到 2040 年電動車也只會佔車市的 1%,而石油業巨頭康菲(ConocoPhillips)也一樣不把電動車當一回事,執行長萊恩蘭斯(Ryan Lance)表示,電動車在 50 年內,甚至在他畢生之內,都不會有實際的影響力,另一家石油巨擘艾克森美孚(Exxon)也看扁電動車市佔只能達到 2%。   然而彭博新能源財經的看法完全相左,認為 2020 年代就會是電動車的時代。電動車的基本經濟層面逐漸往有利的方向發展,其中最重要的就是佔成本相當大比例的電池,在 2015 年電池成本下降 35%,以這個下降速度,6 年內電動車就會比汽油車更具經濟效益,電動車將會迎來市場起飛期,到 2040 年時,長程電動車將要價不到 2.2 萬美元,相當於約 73 萬元新台幣,在這樣的親民價格下,屆時全球 35% 新車銷售都將是電動車。   事實上,不用看到那麼遙遠,就在幾年內,不論是特斯拉(Tesla),雪佛蘭(Chevrolet)、日產(Nissan)等車廠都計劃推出 3 萬美元價位的長程電動車,相當於約百萬元新台幣,其他車廠與 IT 大廠則正投注數以十億美元計的資本,進行相關技術與車種的研發,預期到 2020 年,部分電動車種將會售價比同級汽油車便宜,效能還更好,屆時許多電動車將會銷售勝過同級汽油車,事實上,不用到 2020 年,目前特斯拉的 Model S 銷售就已經勝過同級的汽油高級車。   2015 年電動車銷售成長 60%,大體上與特斯拉預期到 2020 年為止的每年年成長率一致,在歷史上,這也剛好正是福特 T 型車當初取代馬車時的成長率,因此,與石油界所想的相反,電動車起飛很快會對石油需求發生實際影響,彭博社計算,若是電動車繼續以 60% 年成長率成長,最早至 2023 年,而若以比較精確的成長模型計算,至 2028 年,電動車將會減少每日 200 萬桶石油需求,而 2014 年石油價格大崩盤,其實也不過就是供過於求 200 萬桶而已。  
共享服務成為電動車發展推手   彭博新能源財經的較精確估算模型,基本構想是分別計算電動車的各主要零組件以及各種成本下降的情況,考量降價後消費者對電動車接受度的提升幅度,來預期電動車的普及速度,比較電動車與汽油車的維修成本、汽油成本,以及最重要的電池成本。目前電池成本佔電動車總製造成本約三分之一,而鋰電池成本正在快速下降,從過去每度電容量 1,000 美元以上,已經降至 400 美元以下,以彭博新能源財經預估的下降曲線,至 2030 年更有可能降至 100 美元上下。   另一方面則要考慮用電問題,若電動車真的如預期起飛,到 2040 年,將會年消耗 19 億度電力,相當於 2015 年全人類發電量的 10%。不過,電動車本身對電力系統也會有所幫助,電動車所用的電池,老化至容量剩 80% 時就必須汰換,但此時電池用來做為能源儲存用途還綽綽有餘,隨著電動車發展,二次使用的電池也將推動能源儲存,因而促進電網電力更有效的運用,也能推動風能、太陽能等潔淨能源的發展,而能補上電動車的電力需求。   但電池產量大增,不會因為原物料漲價而無法降價嗎?彭博新能源財經計算發現,到 2030 年,製造鋰電池所使用的鋰、鎳、錳、銅,也不過僅佔目前地球已知蘊藏量的 1% 而已,而到了 2030 年以後的新電池,則可能已經不是目前的鋰電池,而是未來的新電池技術,使用不同的原物料,打造更輕薄短小且更便宜的電池。   共享服務如 Uber 與 Lyft 也將成為電動車的推手,共乘機制讓汽車使用率提高,可能 1 年行駛里程數超過 2 萬英里,在如此高里程下,汽油車的維護成本將大為高於電動車,而電動車電池所省下來的汽油成本也將成正比增加,因而使得電池成本攤提下來相對更加便宜,因此彭博新能源財經推估,若是共享服務成功發展,將大為提升電動車市佔率,在 2040 年時達到新車出貨量的 5 成。   不過電動車是否會造成油價崩盤,還有許多變數,如儘管電動車本身成本降低,但是也要配合更多充電站建設才能促使消費者買單,此外。若是油價降至 20 美元且不再回升,低廉的油價本身就會促進石油需求,進而抵銷電動車所減少的汽油需求。但無論如何,電動車起飛只是開端,之後每年都會有更多電動車上路,取代傳統汽油車,而進一步持續減少石油在交通方面的需求,遲早有一天會讓石油走上末路。

(首圖來源: CC BY 2.0)    (本文授權轉載自《》─〈〉)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

南投搬家前需注意的眉眉角角,別等搬了再說!

詳解Spring Security的HttpBasic登錄驗證模式

一、HttpBasic模式的應用場景

HttpBasic登錄驗證模式是Spring Security實現登錄驗證最簡單的一種方式,也可以說是最簡陋的一種方式。它的目的並不是保障登錄驗證的絕對安全,而是提供一種“防君子不防小人”的登錄驗證。

就好像是我小時候寫日記,都買一個帶小鎖頭的日記本,實際上這個小鎖頭有什麼用呢?如果真正想看的人用一根釘子都能撬開。它的作用就是:某天你的父母想偷看你的日記,拿出來一看還帶把鎖,那就算了吧,怪麻煩的。

舉一個我使用HttpBasic模式的進行登錄驗證的例子:我曾經在一個公司擔任部門經理期間,開發了一套用於統計效率、分享知識、生成代碼、導出報表的Http接口。純粹是為了工作中提高效率,同時我又有一點點小私心,畢竟各部之間是有競爭的,所以我給這套接口加上了HttpBasic驗證。公司里隨便一個技術人員,最多只要給上一兩個小時,就可以把這個驗證破解了。說白了,這個工具的數據不那麼重要,加一道鎖的目的就是不讓它成為公開數據。如果有心人破解了,真想看看這裏面的數據,其實也無妨。這就是HttpBasic模式的典型應用場景。

二、spring boot2.0整合Spring security

spring boot 2,x版本maven方式引入Spring security坐標。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

三、HttpBasic登錄認證模式

如果使用的Spring Boot版本為1.X版本,依賴的Security 4.X版本,那麼就無需任何配置,啟動項目訪問則會彈出默認的httpbasic認證.

我們現在使用的是spring boot2.0版本(依賴Security 5.X版本),HttpBasic不再是默認的驗證模式,在spring security 5.x默認的驗證模式已經是表單模式。所以我們要使用Basic模式,需要自己調整一下。並且security.basic.enabled已經過時了,所以我們需要自己去編碼實現。

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
   
   @Override
   protected void configure(HttpSecurity http) throws Exception {
      http.httpBasic()//開啟httpbasic認證
      .and()
      .authorizeRequests()
      .anyRequest()
      .authenticated();//所有請求都需要登錄認證才能訪問
   }

}

啟動項目,在項目後台有這樣的一串日誌打印,冒號後面的就是默認密碼。

Using generated security password: 0cc59a43-c2e7-4c21-a38c-0df8d1a6d624

我們可以通過瀏覽器進行登錄驗證,默認的用戶名是user.(下面的登錄框不是我們開發的,是HttpBasic模式自帶的)

當然我們也可以通過application.yml指定配置用戶名密碼

spring:
    security:
      user:
        name: admin
        password: admin

四、HttpBasic模式的原理說明

  • 首先,HttpBasic模式要求傳輸的用戶名密碼使用Base64模式進行加密。如果用戶名是 "admin"  ,密碼是“ admin”,則將字符串"admin:admin" 使用Base64編碼算法加密。加密結果可能是:YWtaW46YWRtaW4=。
  • 然後,在Http請求中使用Authorization作為一個Header,“Basic YWtaW46YWRtaW4=“作為Header的值,發送給服務端。(注意這裏使用Basic+空格+加密串)
  • 服務器在收到這樣的請求時,到達BasicAuthenticationFilter過濾器,將提取“ Authorization”的Header值,並使用用於驗證用戶身份的相同算法Base64進行解碼。
  • 解碼結果與登錄驗證的用戶名密碼匹配,匹配成功則可以繼續過濾器後續的訪問。

所以,HttpBasic模式真的是非常簡單又簡陋的驗證模式,Base64的加密算法是可逆的,你知道上面的原理,分分鐘就破解掉。我們完全可以使用PostMan工具,發送Http請求進行登錄驗證。

期待您的關注

  • 博主最近新寫了一本書:
  • 本文轉載註明出處(必須帶連接,不能只轉文字):。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家費用,距離,噸數怎麼算?達人教你簡易估價知識!

小白學 Python(22):time 和 calendar 模塊簡單使用

人生苦短,我選Python

前文傳送門

time 模塊

今天我們要介紹的是一個會經常用到的模塊—— time ,顧名思義,這是一個時間相關的模塊。前面我們也介紹過常用模塊,比如 os 模塊,在使用這些模塊前,我們需要先將它導入進來。 time 模塊的導入方式如下:

import time

先來一個簡單的樣例吧:

for i in range(0, 5):
    print(i)
    time.sleep(1)

打印結果我就不展示了,同學們應該都猜得到。那麼 time.sleep(1) 這句話的作用是什麼呢?

sleep() 方法是一個睡眠方法,意思就是程序執行到這裏,需要等待一會,什麼都不做,上面的代碼在執行的時候可以發現,每隔 1s 會打印一個数字, sleep() 裏面給出的參數是休眠的時間,單位是秒。

time 模塊的常用方法

首當其沖當然是獲取當前的時間戳。

print(time.time())

結果如下:

1573054874.6483195

這裏就看不懂了哇,我先來解釋下什麼是時間戳。

在程序中,一般已1970年1月1日0時0分0秒作為起始時間,時間戳就是從起始時間到現在的時長,在 Python 中,這個時長的單位是秒。那麼為什麼起始時間是1970年1月1日0時0分0秒呢?

emmmmmmmmmmmmm,這個我還真不知道,據我所了解的語言,所有的時間戳都是從這個時間點開始起算的。我順手幫各位同學百度了下,表示並沒有找到答案。

不要糾結這個問題了,我們看下一個。

print(time.localtime())

結果如下:

time.struct_time(tm_year=2019, tm_mon=11, tm_mday=6, tm_hour=23, tm_min=47, tm_sec=13, tm_wday=2, tm_yday=310, tm_isdst=0)

這個方法會給出詳細的當前的本地時間,可以細化到年、月、日、小時、分鐘、秒等。

注意: 這個時間是當前本地的計算的時間哦,如果修改計算機的時間,這個值會發生相應的改變的。

print(time.mktime(time.localtime()))

結果如下:

1573055380.0

各位同學看着打印結果應該已經猜到了, mktime() 可以將當前的本地時間轉化為一個時間戳。

以上不管是時間戳、還是本地時間,看起來並不方便,下面我們介紹如何格式化時間。

最簡單的方法,可以使用函數 asctime()

print(time.asctime(time.localtime()))

結果如下:

Wed Nov  6 23:53:52 2019

這個結果還帶着英文,並不符合中國人的習慣嘛,別急,我們還可以自定義格式。

print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))

結果如下:

2019-11-06 23:55:56

這樣看着就舒服多了么,我們可以通過 strftime() 來自定義日期格式。

這裏列舉一下日期格式化的符號:

  • %y 兩位數的年份表示(00-99)
  • %Y 四位數的年份表示(000-9999)
  • %m 月份(01-12)
  • %d 月內中的一天(0-31)
  • %H 24小時制小時數(0-23)
  • %I 12小時制小時數(01-12)
  • %M 分鐘數(00=59)
  • %S 秒(00-59)
  • %a 本地簡化星期名稱
  • %A 本地完整星期名稱
  • %b 本地簡化的月份名稱
  • %B 本地完整的月份名稱
  • %c 本地相應的日期表示和時間表示
  • %j 年內的一天(001-366)
  • %p 本地A.M.或P.M.的等價符
  • %U 一年中的星期數(00-53)星期天為星期的開始
  • %w 星期(0-6),星期天為星期的開始
  • %W 一年中的星期數(00-53)星期一為星期的開始
  • %x 本地相應的日期表示
  • %X 本地相應的時間表示
  • %Z 當前時區的名稱
  • %% %號本身

哇,這也太多了,記不住怎麼辦?

其實這個並不需要你都記下來,只需要記住常用的就好了,就比如我上面使用的年、月、日、時、分、秒。其餘的不常用的可以在有需要的時候再來查表。

有時候時間之間不使用短橫杠 - 來隔開,而選擇使用斜杠 / 隔開,這個怎麼辦?

這個很簡單咯,看我的:

print(time.strftime("%Y/%m/%d %H:%M:%S", time.localtime()))

結果如下:

2019/11/07 00:02:18

calendar 模塊

都聊到這裏了,我們順便再聊一個模塊,日曆。

先看下代碼演示吧,這個就比較有意思了:

import calendar

print(calendar.calendar(theyear=2020, w=2, l=1, c=6))

結果如下:

                                  2020

      January                   February                   March
Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su
       1  2  3  4  5                      1  2                         1
 6  7  8  9 10 11 12       3  4  5  6  7  8  9       2  3  4  5  6  7  8
13 14 15 16 17 18 19      10 11 12 13 14 15 16       9 10 11 12 13 14 15
20 21 22 23 24 25 26      17 18 19 20 21 22 23      16 17 18 19 20 21 22
27 28 29 30 31            24 25 26 27 28 29         23 24 25 26 27 28 29
                                                    30 31

       April                      May                       June
Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su
       1  2  3  4  5                   1  2  3       1  2  3  4  5  6  7
 6  7  8  9 10 11 12       4  5  6  7  8  9 10       8  9 10 11 12 13 14
13 14 15 16 17 18 19      11 12 13 14 15 16 17      15 16 17 18 19 20 21
20 21 22 23 24 25 26      18 19 20 21 22 23 24      22 23 24 25 26 27 28
27 28 29 30               25 26 27 28 29 30 31      29 30

        July                     August                  September
Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su
       1  2  3  4  5                      1  2          1  2  3  4  5  6
 6  7  8  9 10 11 12       3  4  5  6  7  8  9       7  8  9 10 11 12 13
13 14 15 16 17 18 19      10 11 12 13 14 15 16      14 15 16 17 18 19 20
20 21 22 23 24 25 26      17 18 19 20 21 22 23      21 22 23 24 25 26 27
27 28 29 30 31            24 25 26 27 28 29 30      28 29 30
                          31

      October                   November                  December
Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su
          1  2  3  4                         1          1  2  3  4  5  6
 5  6  7  8  9 10 11       2  3  4  5  6  7  8       7  8  9 10 11 12 13
12 13 14 15 16 17 18       9 10 11 12 13 14 15      14 15 16 17 18 19 20
19 20 21 22 23 24 25      16 17 18 19 20 21 22      21 22 23 24 25 26 27
26 27 28 29 30 31         23 24 25 26 27 28 29      28 29 30 31
                          30

我們把 2020 年的日曆打印出來了。

  • w = 每個日期之間的間隔字符數
  • l = 每周所佔用的行數
  • c = 每個月之間的間隔字符數

以後我們看日曆可以使用這個函數看了。

要用你們用,反正我是不用,我選擇使用這個:

除了直接返回全年的日曆,calendar 還支持返回指定月份的日曆:

print(calendar.month(2019, 11))

結果如下:

   November 2019
Mo Tu We Th Fr Sa Su
             1  2  3
 4  5  6  7  8  9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30

我們還可以直接獲得某月的總天數:

print(calendar.monthlen(2019, 11))

結果如下:

30

這個功能好像有點雞肋,我們獲取某月的天數難道不是都靠那句兒歌么?

一三五七八十臘,三十一天永不差

我們還可以知道指定的日期對應的星期數:

print(calendar.weekday(2019, 11, 7))

結果如下:

3

這個我覺得蠻實用的,再也不用自己寫算法去推算了。

示例代碼

本系列的所有代碼小編都會放在代碼管理倉庫 Github 和 Gitee 上,方便大家取用。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

南投搬家前需注意的眉眉角角,別等搬了再說!

特斯拉第 2 季銷量暴增逾 5 成 世德及和大受惠

美國電動車大廠特斯拉(Tesla)第二季銷量暴增超過 50%,激勵國內相關概念股飆漲,其中世德攻上漲停價位、和大則再創歷史新高。   特斯拉公布最新數據,第二季電動車銷量增加至 1.15 萬輛,暴增 52%,比市場先前估算的 1~1.1 萬輛還多,為連續第二個季度表現優於市場預期,激勵國內大廠股價向上走高。   以世德來說,身為特斯拉供應鏈廠,隨著客戶銷量增加、推出新款車型,加上對其供貨金額占比提升 2 倍至 8%,市場看好其後市發展,對其紛紛敲下滿單。   而和大因是特斯拉電動車減速齒輪唯一供應商,隨著客戶的新車種由兩輪傳動提升為四輪傳動,需要多一顆前輪減速齒輪箱,法人預估,和大今年來自 Tesla 的訂單、營收將成長超過 1 倍。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家費用,距離,噸數怎麼算?達人教你簡易估價知識!

006.Kubernetes二進制部署ETCD

一 部署ETCD集群

1.1 安裝ETCD


etcd 是基於 Raft 的分佈式 key-value 存儲系統,由 CoreOS 開發,常用於服務發現、共享配置以及併發控制(如 leader 選舉、分佈式鎖等)。kubernetes 使用 etcd 存儲所有運行數據。

  1 etcd 是基於 Raft 的分佈式 key-value 存儲系統,由 CoreOS 開發,常用於服務發現、共享配置以及併發控制(如 leader 選舉、分佈式鎖等)。kubernetes 使用 etcd 存儲所有運行數據。
  2 [root@k8smaster01 ~]# cd /opt/k8s/work
  3 [root@k8smaster01 work]# wget https://github.com/coreos/etcd/releases/download/v3.3.13/etcd-v3.3.13-linux-amd64.tar.gz
  4 [root@k8smaster01 work]# tar -xvf etcd-v3.3.13-linux-amd64.tar.gz


1.2 分發ETCD

  1 [root@k8smaster01 ~]# cd /opt/k8s/work
  2 [root@k8smaster01 work]# source /opt/k8s/bin/environment.sh
  3 [root@k8smaster01 work]# for master_ip in ${MASTER_IPS[@]}
  4   do
  5     echo ">>> ${master_ip}"
  6     scp etcd-v3.3.13-linux-amd64/etcd* root@${master_ip}:/opt/k8s/bin
  7     ssh root@${master_ip} "chmod +x /opt/k8s/bin/*"
  8   done


1.3 創建etcd證書和密鑰

  1 [root@k8smaster01 ~]# cd /opt/k8s/work
  2 [root@k8smaster01 work]# cat > etcd-csr.json <<EOF
  3 {
  4     "CN": "etcd",
  5     "hosts": [
  6     "127.0.0.1",
  7     "172.24.8.71",
  8     "172.24.8.72",
  9     "172.24.8.73"
 10   ],
 11     "key": {
 12         "algo": "rsa",
 13         "size": 2048
 14     },
 15     "names": [
 16         {
 17             "C": "CN",
 18             "ST": "Shanghai",
 19             "L": "Shanghai",
 20             "O": "k8s",
 21             "OU": "System"
 22         }
 23     ]
 24 }
 25 EOF
 26 #創建etcd的CA證書請求文件



解釋:

hosts 字段指定授權使用該證書的 etcd 節點 IP 或域名列表,需要將 etcd 集群的三個節點 IP 都列在其中。

  1 [root@k8smaster01 ~]# cd /opt/k8s/work
  2 [root@k8smaster01 work]# cfssl gencert -ca=/opt/k8s/work/ca.pem \
  3 -ca-key=/opt/k8s/work/ca-key.pem -config=/opt/k8s/work/ca-config.json \
  4 -profile=kubernetes etcd-csr.json | cfssljson -bare etcd	#生成CA密鑰(ca-key.pem)和證書(ca.pem)


1.4 分發證書和私鑰

  1 [root@k8smaster01 ~]# cd /opt/k8s/work
  2 [root@k8smaster01 work]# source /opt/k8s/bin/environment.sh
  3 [root@k8smaster01 work]# for master_ip in ${MASTER_IPS[@]}
  4   do
  5     echo ">>> ${master_ip}"
  6     ssh root@${master_ip} "mkdir -p /etc/etcd/cert"
  7     scp etcd*.pem root@${master_ip}:/etc/etcd/cert/
  8   done


1.5 創建etcd的systemd

  1 [root@k8smaster01 ~]# cd /opt/k8s/work
  2 [root@k8smaster01 work]# source /opt/k8s/bin/environment.sh
  3 [root@k8smaster01 work]# cat > etcd.service.template <<EOF
  4 [Unit]
  5 Description=Etcd Server
  6 After=network.target
  7 After=network-online.target
  8 Wants=network-online.target
  9 Documentation=https://github.com/coreos
 10 
 11 [Service]
 12 Type=notify
 13 WorkingDirectory=${ETCD_DATA_DIR}
 14 ExecStart=/opt/k8s/bin/etcd \\
 15   --data-dir=${ETCD_DATA_DIR} \\
 16   --wal-dir=${ETCD_WAL_DIR} \\
 17   --name=##MASTER_NAME## \\
 18   --cert-file=/etc/etcd/cert/etcd.pem \\
 19   --key-file=/etc/etcd/cert/etcd-key.pem \\
 20   --trusted-ca-file=/etc/kubernetes/cert/ca.pem \\
 21   --peer-cert-file=/etc/etcd/cert/etcd.pem \\
 22   --peer-key-file=/etc/etcd/cert/etcd-key.pem \\
 23   --peer-trusted-ca-file=/etc/kubernetes/cert/ca.pem \\
 24   --peer-client-cert-auth \\
 25   --client-cert-auth \\
 26   --listen-peer-urls=https://##MASTER_IP##:2380 \\
 27   --initial-advertise-peer-urls=https://##MASTER_IP##:2380 \\
 28   --listen-client-urls=https://##MASTER_IP##:2379,http://127.0.0.1:2379 \\
 29   --advertise-client-urls=https://##MASTER_IP##:2379 \\
 30   --initial-cluster-token=etcd-cluster-0 \\
 31   --initial-cluster=${ETCD_NODES} \\
 32   --initial-cluster-state=new \\
 33   --auto-compaction-mode=periodic \\
 34   --auto-compaction-retention=1 \\
 35   --max-request-bytes=33554432 \\
 36   --quota-backend-bytes=6442450944 \\
 37   --heartbeat-interval=250 \\
 38   --election-timeout=2000
 39 Restart=on-failure
 40 RestartSec=5
 41 LimitNOFILE=65536
 42 
 43 [Install]
 44 WantedBy=multi-user.target
 45 EOF



解釋:

WorkingDirectory、–data-dir:指定工作目錄和數據目錄為 ${ETCD_DATA_DIR},需在啟動服務前創建這個目錄;

–wal-dir:指定 wal 目錄,為了提高性能,一般使用 SSD 或者和 –data-dir 不同的磁盤;

–name:指定節點名稱,當 –initial-cluster-state 值為 new 時,–name 的參數值必須位於 –initial-cluster 列表中;

–cert-file、–key-file:etcd server 與 client 通信時使用的證書和私鑰;

–trusted-ca-file:簽名 client 證書的 CA 證書,用於驗證 client 證書;

–peer-cert-file、–peer-key-file:etcd 與 peer 通信使用的證書和私鑰;

–peer-trusted-ca-file:簽名 peer 證書的 CA 證書,用於驗證 peer 證書。

1.6 修改systemd相應地址

  1 [root@k8smaster01 ~]# cd /opt/k8s/work
  2 [root@k8smaster01 work]# source /opt/k8s/bin/environment.sh
  3 [root@k8smaster01 work]# for (( i=0; i < 3; i++ ))
  4   do
  5     sed -e "s/##MASTER_NAME##/${MASTER_NAMES[i]}/" -e "s/##MASTER_IP##/${MASTER_IPS[i]}/" etcd.service.template > etcd-${MASTER_IPS[i]}.service
  6   done


1.7 分發etcd systemd

  1 [root@k8smaster01 ~]# cd /opt/k8s/work
  2 [root@k8smaster01 work]# source /opt/k8s/bin/environment.sh
  3 [root@k8smaster01 work]# for master_ip in ${MASTER_IPS[@]}
  4   do
  5     echo ">>> ${master_ip}"
  6     scp etcd-${master_ip}.service root@${master_ip}:/etc/systemd/system/etcd.service
  7   done


二 啟動並驗證

2.1 啟動ETCD

  1 [root@k8smaster01 ~]# cd /opt/k8s/work
  2 [root@k8smaster01 work]# source /opt/k8s/bin/environment.sh
  3 [root@k8smaster01 work]# for master_ip in ${MASTER_IPS[@]}
  4   do
  5     echo ">>> ${master_ip}"
  6     ssh root@${master_ip} "mkdir -p ${ETCD_DATA_DIR} ${ETCD_WAL_DIR}"
  7     ssh root@${master_ip} "systemctl daemon-reload && systemctl enable etcd && systemctl restart etcd " &
  8   done


2.2 檢查ETCD啟動

  1 [root@k8smaster01 ~]# cd /opt/k8s/work
  2 [root@k8smaster01 work]# source /opt/k8s/bin/environment.sh
  3 [root@k8smaster01 work]# for master_ip in ${MASTER_IPS[@]}
  4   do
  5     echo ">>> ${master_ip}"
  6     ssh root@${master_ip} "systemctl status etcd|grep Active"
  7   done


2.3 驗證服務狀態

  1 [root@k8smaster01 ~]# cd /opt/k8s/work
  2 [root@k8smaster01 work]# source /opt/k8s/bin/environment.sh
  3 [root@k8smaster01 work]# for master_ip in ${MASTER_IPS[@]}
  4   do
  5     echo ">>> ${master_ip}"
  6     ETCDCTL_API=3 /opt/k8s/bin/etcdctl \
  7     --endpoints=https://${master_ip}:2379 \
  8     --cacert=/etc/kubernetes/cert/ca.pem \
  9     --cert=/etc/etcd/cert/etcd.pem \
 10     --key=/etc/etcd/cert/etcd-key.pem endpoint health
 11   done



2.4 查看ETCD當前leader

  1 [root@k8smaster01 ~]# source /opt/k8s/bin/environment.sh
  2 [root@k8smaster01 ~]# ETCDCTL_API=3 /opt/k8s/bin/etcdctl \
  3   -w table --cacert=/etc/kubernetes/cert/ca.pem \
  4   --cert=/etc/etcd/cert/etcd.pem \
  5   --key=/etc/etcd/cert/etcd-key.pem \
  6   --endpoints=${ETCD_ENDPOINTS} endpoint status




如上所示,當前ETCD集群的leader為172.24.8.71。本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家費用,距離,噸數怎麼算?達人教你簡易估價知識!

淺談什麼是動態規劃以及相關的「股票」算法題:一網打盡「買賣股票的最佳時機」

本文首發於公眾號「五分鐘學算法」,是系列文章之一。

個人網站:

動態規劃

1 概念

  動態規劃算法是通過拆分問題,定義問題狀態和狀態之間的關係,使得問題能夠以遞推(或者說分治)的方式去解決。在學習動態規劃之前需要明確掌握幾個重要概念。

  階段:對於一個完整的問題過程,適當的切分為若干個相互聯繫的子問題,每次在求解一個子問題,則對應一個階段,整個問題的求解轉化為按照階段次序去求解。

  狀態:狀態表示每個階段開始時所處的客觀條件,即在求解子問題時的已知條件。狀態描述了研究的問題過程中的狀況。

  決策:決策表示當求解過程處於某一階段的某一狀態時,可以根據當前條件作出不同的選擇,從而確定下一個階段的狀態,這種選擇稱為決策。

  策略:由所有階段的決策組成的決策序列稱為全過程策略,簡稱策略。

  最優策略:在所有的策略中,找到代價最小,性能最優的策略,此策略稱為最優策略。

  狀態轉移方程:狀態轉移方程是確定兩個相鄰階段狀態的演變過程,描述了狀態之間是如何演變的。

2 使用場景

能採用動態規劃求解的問題的一般要具有 3 個性質:

  (1)最優化:如果問題的最優解所包含的子問題的解也是最優的,就稱該問題具有最優子結構,即滿足最優化原理。子問題的局部最優將導致整個問題的全局最優。換句話說,就是問題的一個最優解中一定包含子問題的一個最優解。

  (2)無後效性:即某階段狀態一旦確定,就不受這個狀態以後決策的影響。也就是說,某狀態以後的過程不會影響以前的狀態,只與當前狀態有關,與其他階段的狀態無關,特別是與未發生的階段的狀態無關。

   (3)重疊子問題:即子問題之間是不獨立的,一個子問題在下一階段決策中可能被多次使用到。(該性質並不是動態規劃適用的必要條件,但是如果沒有這條性質,動態規劃算法同其他算法相比就不具備優勢)

3 算法流程

  (1)劃分階段:按照問題的時間或者空間特徵將問題劃分為若干個階段。
  (2)確定狀態以及狀態變量:將問題的不同階段時期的不同狀態描述出來。
  (3)確定決策並寫出狀態轉移方程:根據相鄰兩個階段的各個狀態之間的關係確定決策。
  (4)尋找邊界條件:一般而言,狀態轉移方程是遞推式,必須有一個遞推的邊界條件。
  (5)設計程序,解決問題

實戰練習

下面的三道算法題都是來源於 LeetCode 上與股票買賣相關的問題 ,我們按照 動態規劃 的算法流程來處理該類問題。

股票買賣這一類的問題,都是給一個輸入數組,裏面的每個元素表示的是每天的股價,並且你只能持有一支股票(也就是你必須在再次購買前出售掉之前的股票),一般來說有下面幾種問法:

  • 只能買賣一次
  • 可以買賣無數次
  • 可以買賣 k 次

需要你設計一個算法去獲取最大的利潤。

買賣股票的最佳時機

題目來源於 LeetCode 上第 121 號問題:買賣股票的最佳時機。題目難度為 Easy,目前通過率為 49.4% 。

題目描述

給定一個數組,它的第 i 個元素是一支給定股票第 i 天的價格。

如果你最多只允許完成一筆交易(即買入和賣出一支股票),設計一個算法來計算你所能獲取的最大利潤。

注意你不能在買入股票前賣出股票。

示例 1:

輸入: [7,1,5,3,6,4]
輸出: 5
解釋: 在第 2 天(股票價格 = 1)的時候買入,在第 5 天(股票價格 = 6)的時候賣出,最大利潤 = 6-1 = 5 。
     注意利潤不能是 7-1 = 6, 因為賣出價格需要大於買入價格。

示例 2:

輸入: [7,6,4,3,1]
輸出: 0
解釋: 在這種情況下, 沒有交易完成, 所以最大利潤為 0。

題目解析

我們按照動態規劃的思想來思考這道問題。

狀態

買入(buy)賣出(sell) 這兩種狀態。

轉移方程

對於買來說,買之後可以賣出(進入賣狀態),也可以不再進行股票交易(保持買狀態)。

對於賣來說,賣出股票后不在進行股票交易(還在賣狀態)。

只有在手上的錢才算錢,手上的錢購買當天的股票后相當於虧損。也就是說當天買的話意味着損失-prices[i],當天賣的話意味着增加prices[i],當天賣出總的收益就是 buy+prices[i]

所以我們只要考慮當天買和之前買哪個收益更高,當天賣和之前賣哪個收益更高。

  • buy = max(buy, -price[i]) (注意:根據定義 buy 是負數)
  • sell = max(sell, prices[i] + buy)

邊界

第一天 buy = -prices[0], sell = 0,最後返回 sell 即可。

代碼實現

class Solution {
    public int maxProfit(int[] prices) {
        if(prices.length <= 1)
            return 0;
        int buy = -prices[0], sell = 0;
        for(int i = 1; i < prices.length; i++) {
            buy = Math.max(buy, -prices[i]);
            sell = Math.max(sell, prices[i] + buy);

        }
        return sell;
    }
}

買賣股票的最佳時機 II

題目來源於 LeetCode 上第 122 號問題:買賣股票的最佳時機 II。題目難度為 Easy,目前通過率為 53.0% 。

題目描述

給定一個數組,它的第 i 個元素是一支給定股票第 i 天的價格。

設計一個算法來計算你所能獲取的最大利潤。你可以盡可能地完成更多的交易(多次買賣一支股票)。

注意:你不能同時參与多筆交易(你必須在再次購買前出售掉之前的股票)。

示例 1:

輸入: [7,1,5,3,6,4]
輸出: 7
解釋: 在第 2 天(股票價格 = 1)的時候買入,在第 3 天(股票價格 = 5)的時候賣出, 這筆交易所能獲得利潤 = 5-1 = 4 。
     隨後,在第 4 天(股票價格 = 3)的時候買入,在第 5 天(股票價格 = 6)的時候賣出, 這筆交易所能獲得利潤 = 6-3 = 3 。

示例 2:

輸入: [1,2,3,4,5]
輸出: 4
解釋: 在第 1 天(股票價格 = 1)的時候買入,在第 5 天 (股票價格 = 5)的時候賣出, 這筆交易所能獲得利潤 = 5-1 = 4 。
     注意你不能在第 1 天和第 2 天接連購買股票,之後再將它們賣出。
     因為這樣屬於同時參与了多筆交易,你必須在再次購買前出售掉之前的股票。

示例 3:

輸入: [7,6,4,3,1]
輸出: 0
解釋: 在這種情況下, 沒有交易完成, 所以最大利潤為 0。

題目解析

狀態

買入(buy)賣出(sell) 這兩種狀態。

轉移方程

對比上題,這裏可以有無限次的買入和賣出,也就是說 買入 狀態之前可擁有 賣出 狀態,所以買入的轉移方程需要變化。

  • buy = max(buy, sell – price[i])
  • sell = max(sell, buy + prices[i] )

邊界

第一天 buy = -prices[0], sell = 0,最後返回 sell 即可。

代碼實現

class Solution {
    public int maxProfit(int[] prices) {
        if(prices.length <= 1)
            return 0;
        int buy = -prices[0], sell = 0;
        for(int i = 1; i < prices.length; i++) {
            sell = Math.max(sell, prices[i] + buy);
            buy = Math.max( buy,sell - prices[i]);
        }
        return sell;
    }
}

買賣股票的最佳時機 III

題目來源於 LeetCode 上第 123 號問題:買賣股票的最佳時機 III。題目難度為 Hard,目前通過率為 36.1% 。

題目描述

給定一個數組,它的第 i 個元素是一支給定的股票在第 i 天的價格。

設計一個算法來計算你所能獲取的最大利潤。你最多可以完成 兩筆 交易。

注意: 你不能同時參与多筆交易(你必須在再次購買前出售掉之前的股票)。

示例 1:

輸入: [3,3,5,0,0,3,1,4]
輸出: 6
解釋: 在第 4 天(股票價格 = 0)的時候買入,在第 6 天(股票價格 = 3)的時候賣出,這筆交易所能獲得利潤 = 3-0 = 3 。
     隨後,在第 7 天(股票價格 = 1)的時候買入,在第 8 天 (股票價格 = 4)的時候賣出,這筆交易所能獲得利潤 = 4-1 = 3 。

示例 2:

輸入: [1,2,3,4,5]
輸出: 4
解釋: 在第 1 天(股票價格 = 1)的時候買入,在第 5 天 (股票價格 = 5)的時候賣出, 這筆交易所能獲得利潤 = 5-1 = 4 。   
     注意你不能在第 1 天和第 2 天接連購買股票,之後再將它們賣出。   
     因為這樣屬於同時參与了多筆交易,你必須在再次購買前出售掉之前的股票。

示例 3:

輸入: [7,6,4,3,1] 
輸出: 0 
解釋: 在這個情況下, 沒有交易完成, 所以最大利潤為 0。

題目解析

這裏限制了最多兩筆交易。

狀態

第一次買入(fstBuy)第一次賣出(fstSell)第二次買入(secBuy)第二次賣出(secSell) 這四種狀態。

轉移方程

這裏最多兩次買入和兩次賣出,也就是說 買入 狀態之前可擁有 賣出 狀態,賣出 狀態之前可擁有 買入 狀態,所以買入和賣出的轉移方程都需要變化。

  • fstBuy = max(fstBuy , -price[i])
  • fstSell = max(fstSell,fstBuy + prices[i] )
  • secBuy = max(secBuy ,fstSell -price[i]) (受第一次賣出狀態的影響)
  • secSell = max(secSell ,secBuy + prices[i] )

邊界

  • 一開始 fstBuy = -prices[0]
  • 買入后直接賣出,fstSell = 0
  • 買入后再賣出再買入,secBuy - prices[0]
  • 買入后再賣出再買入再賣出,secSell = 0

最後返回 secSell 。

代碼實現

class Solution {
    public int maxProfit(int[] prices) {
        int fstBuy = Integer.MIN_VALUE, fstSell = 0;
        int secBuy = Integer.MIN_VALUE, secSell = 0;
        for(int i = 0; i < prices.length; i++) {
            fstBuy = Math.max(fstBuy, -prices[i]);
            fstSell = Math.max(fstSell, fstBuy + prices[i]);
            secBuy = Math.max(secBuy, fstSell -  prices[i]);
            secSell = Math.max(secSell, secBuy +  prices[i]); 
        }
        return secSell;

    }
}

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

南投搬家前需注意的眉眉角角,別等搬了再說!

特斯拉、Airbnb 合作,至少百間民宿將加裝電動車充電座

  對於特斯拉(Tesla)的充電式電動車而言,最大普及障礙就是充電座設施的密度,如果只能在自己家充電,那電動車的作用就相當有限了,為此,特斯拉找上了分享經濟旅遊住宿網站 Airbnb,與其旗下的民宿合作,在民宿安裝 Model S 電動車充電座,這樣一來旅遊住宿時也能充電,擴增 Model S 電動車車主的活動範圍。   特斯拉將根據資格標準審查,包括要四星級以上、並至少有 5 個房間,符合水準的 Airbnb 旗下高檔民宿,可獲得免費充電座,充電座本身價值 750 美元,不過民宿本身要負擔安裝費用,安裝費用隨地區不同,可能超過 900 美元,安裝完成後,Airbnb 將在網站上標示該民宿為特斯拉電動車可充電民宿。特斯拉初期將先從加州開始,選擇 30 家加州 Airbnb 旗下高檔民宿免費安裝充電座,之後再逐步擴大到全球,目前只有 12 戶民宿擁有特斯拉充電座,最終將至少有 100 家 Airbnb 旗下民宿可得到免費充電座。   這只是特斯拉積極建立充電站努力的其中一環,特斯拉正積極布建其 Supercharger 快速充電站,目前全球已有 487 座,也與餐廳、旅館、度假村合作,在其中建立壁式充電座,方便車主造訪時順便充電,至 2015 年 6 月,特斯拉在全球已經與 1,200 家業主合作設立充電座。   Airbnb 旗下民宿與特斯拉合作可說是雙贏選擇,雖然仍需負擔安裝費用,但安裝後,可吸引大多為高階消費者的特斯拉車主入住,不僅對生意與品牌形象有幫助,車主充電付出充電費用,一個晚上大約可增加 10 美元營收,對民宿不無小補。而對特斯拉來說,充電座越普及,車子也更好賣。   特斯拉目前大體上只在美國主要城市與幹道路線上布置充電座,經常遭到質疑與攻擊,聲稱電動車可能會在荒郊野外沒電,儘管特斯拉嚴詞反擊目前布站範圍已經涵蓋 96% 美國地區,要故意開到離充電站遠到來不及去充電的地區沒那麼容易,但特斯拉對這樣的抨擊也不敢怠慢,2015 年 3 月時推出軟體更新,整合充電站位置到導航系統之中,一旦車主離充電站距離可能超出殘餘電力可行駛里程,就發出警告,確保不會發生半途沒電的情況。   但要讓潛在消費者更安心買車,最根本之道仍是布建更多充電站,與 Airbnb 的合作代表特斯拉又向前跨出一步,未來可預期特斯拉將更積極推動類似的合作案。     本文全文授權轉載自《科技新報》─〈〉

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家費用,距離,噸數怎麼算?達人教你簡易估價知識!