iT邦幫忙

1

用go cache存質數表

  • 分享至 

  • xImage

我這東西想了很久。我想要用go cache套件存取質數表,以下是我的程式碼。https://ithelp.ithome.com.tw/upload/images/20230822/20162136EtjEW2at8Z.png

這邊的QueryCachePrimesInRange()我是想說先看cache裡面的值有沒有東西,如果有值,則先更新cache,cache中有不重複的質數表,從裡面拉出符合start,end區間的質數,如果沒有值就去更新cache,然後再查一次輸出當前答案。
https://ithelp.ithome.com.tw/upload/images/20230822/20162136klYzcHzGvD.png

這兩個函式UpdateCachePrimeRange、mergeAndRemoveDuplicates,我是希望用來更新cache的值且不讓他重複,讓他像質數表那樣存著,calculate是算出質數的函式。
https://ithelp.ithome.com.tw/upload/images/20230822/20162136tXnLYihUid.png

但測試的時候有時輸出正常有時沒有值,感覺很像是update那邊出問題,請大神告訴我到底錯在哪裡,或是給我另一個想法關於如何用cache存質數表。

如果要更詳細的程式我會即時更新

圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
1
海綿寶寶
iT邦大神 1 級 ‧ 2023-08-23 07:35:28
最佳解答

我看了幾遍,終於看出問題

cache 的基本概念就是 key-value
用 key 查詢,有兩種結果
1.找得到, 回傳 value 即是查詢結果
2.找不到, 將「別的地方來的值(eg.資料庫或計算結果)」存入 cache 並回傳 value

這篇是個很簡單扼要的範例

由此可以看出,key 的定義
比對你的程式
你查詢用的是 start 和 end
但你的 key 值卻是 prime 定字
這代表不管你用什麼 start,end,每次查詢cache都會「找得到」
結果自然不如預期

等你想通之後,你會發現
程式比原來這個版本簡單很多

另外請教
真正原始的題目是不是「用 cache 機制改善 isPrime 函數的效能」
而不是「用go cache存質數表」?

看更多先前的回應...收起先前的回應...
brown125 iT邦新手 5 級 ‧ 2023-08-23 11:02:06 檢舉

的確是沒錯,只是我自己選擇用go cache做XD,但我想了很久想不太到怎麼解決,我之前有寫成讓他查詢裡面的value有沒有對到查詢區間的質數,但整個就很大一包,可能缺少靈感XD

如果是我會這樣寫, 參考看看

isPrime(x) : 判斷 x 是否是質數
start, end
cachePrimes : 存放質數的 cache
result : 存放結果的變數

for i = start to end {
   if i in cachePrimes { #代表 i 是質數
      result.add(i)
   } else {
      if isPrime(i) { #是質數
          result.add(i)
          cachePrimes.add(i)
      }
   }
}

寫完收工放飯
/images/emoticon/emoticon71.gif

上面的寫法是基於「用 cache 存質數表」的命題
其實比較完整的寫法應該是
存放所有數字,以及其是否為質數
如此才可以達到
每個數字判斷是否為質數的動作, 只需做一次即可

isPrime(x) : 判斷 x 是否是質數
start, end
cachePrimes : 存放所有數字的 cache
result : 存放結果的變數

for i = start to end {
   if i in cachePrimes { 
      if cachePrimes(i) = 'Y' {#是質數
          result.add(i)
      }
   } else {
      if isPrime(i) { #是質數
          result.add(i)
          cachePrimes.add(i, 'Y')
      } else {
          cachePrimes.add(i, 'N')
      }
   }
}
brown125 iT邦新手 5 級 ‧ 2023-08-23 13:46:44 檢舉

感謝尼,我等下來實作看看
https://ithelp.ithome.com.tw/upload/images/20230823/20162136yIkHexoRLD.png
這樣的確有把query和update的功能合起來,測資也比我自己想的快。太猛了

2
一級屠豬士
iT邦大師 1 級 ‧ 2023-08-22 23:12:13

用資料庫做範圍查詢就好.

這裡就有已經計算好的

ttps://www.mathsisfun.com/numbers/prime-number-lists.html

舉例就只下載第一部分:
wget https://www.mathsisfun.com/includes/primes-to-100k.zip
解壓
unzip primes-to-100k.zip

建立table

create table primes (
  id bigint not null generated always as identity primary key
, prime decimal(16)
);

將primes-to-100k.txt 載入

\copy primes(prime) from 'primes-to-100k.txt'

列出 500 ~ 1000 之間的質數

select prime
  from primes
 where prime >= 500
   and prime <= 1000;

 prime
-------
   503
   509
   521
   523
   541
   547
   557
   563
   569
   571
   577
   587
   593
   599
   601
   607
   613
   617
   619
   631
   641
   643
   647
   653
   659
   661
   673
   677
   683
   691
   701
   709
   719
   727
   733
   739
   743
   751
   757
   761
   769
   773
   787
   797
   809
   811
   821
   823
   827
   829
   839
   853
   857
   859
   863
   877
   881
   883
   887
   907
   911
   919
   929
   937
   941
   947
   953
   967
   971
   977
   983
   991
   997
(73 rows)

看更多先前的回應...收起先前的回應...
brown125 iT邦新手 5 級 ‧ 2023-08-22 23:35:33 檢舉

這個其實算是主管要求的XDD 所以一定要用cache 資料表我自己實作過是OK

為何要用 range 當key , 然後存一串質數 ?

obarisk iT邦研究生 1 級 ‧ 2023-08-23 12:05:35 檢舉

就算不用 sql,直接開 go 把資料載入到記憶體,
用記憶體的 sql 查

速度大概很難輸給你自己寫的程式(無誤)

看起來是公司主管出的考題~驗證寫Go的能力

froce iT邦大師 1 級 ‧ 2023-08-23 15:27:16 檢舉

就算不用 sql,直接開 go 把資料載入到記憶體

其實我也很想這樣回,cache又不是只有redis才叫cache。
啟動時直接把預設的質數表丟到記憶體裡也行,注意一下鎖的問題就好。
或是乾脆在記憶體裡弄個sqlite。
另外go-cache沒有query功能,所以他要的這個一定得自己操作redis。

0
whitefloor
iT邦研究生 2 級 ‧ 2023-08-23 09:50:45

merge的地方出了問題吧

你把已經算好的質數陣列列表拿去跟新算好做比較這沒問題
問題是你existingMap跟merged是兩個東西
這時候[]newValues int{}只要是空陣列完全沒東西
existingMap就直接吐空的merged回去了
應該是要比較existingMap沒有就加進去而且return existingMap
轉型也沒做檢查跟沒處理err
演算法也有問題,每次都要sort時間複雜度超高

下次程式碼別用截圖的,而且附上你的測試資料
然後沒事就到處print

0
obarisk
iT邦研究生 1 級 ‧ 2023-08-23 12:10:22

這個問題問的不好

要簡化問題。

如果是質數問題,就只問質數問題。
如果是 cache,就只問 cache 的問題就好了。

cache 大概要考慮的東西

  • 是否是 thread safe
  • 是否有 persisten 功能(儲存/載入)
  • 空間複雜度
  • 時間複雜度

如果不需要 thread safe,直接用 map/slice 弄就可以了。
只是需要設計一個方便寫方便讀,時間複雜度/空間複雜度在可以接受範圍內的解法就可以了


By the way. 真看不出你主管是好人還是壞人了
給了很多空間可以亂玩
但是方向似乎給的不夠

brown125 iT邦新手 5 級 ‧ 2023-08-23 13:25:13 檢舉

感謝,這我的確要想想,mentor的風格感覺是你想怎麼走方向你自己決定,到的了就好XD 我也還在適應

我要發表回答

立即登入回答