#26848: [Python]這題可以不使用浮點運算,但要小心Python的負數整除運算 //


406490150@gms.tku.edu.tw (我是朱朱)

學校 : 國立交通大學
編號 : 139794
來源 : [140.113.236.122]
最後登入時間 :
2022-09-03 11:13:16
e948. 基礎代謝率 (BMR Calculation) -- TOI練習賽201903新手組第1題 | From: [36.238.104.152] | 發表日期 : 2021-08-27 22:34

一、

這題其實可以不使用浮點運算,如果你仔細看測資的答案,會發現怎麼尾數都一定是0,這不是巧合。

如果你觀察輸入與公式,會發現只有一位小數點要計算,其實就可以先把公式*10,算出的答案再/10即可。

改寫後的公式像這樣:

BMR_boy =  lambda A,C,M: (137*M) + (50*C) - (68*A) + 660
BMR_girl = lambda A,C,M:  (96*M) + (18*C) - (47*A) + 6550

 

要注意最後一個整數,記得*10

____________________________

二、

在輸出的時候,如果直接使用 q,r = divmod(BMR, 10) ,在BMR是負數的時候有可能產生問題

這因為Python想要使 q*10+r == BMR  永遠成立,

在做餘數運算A%B的時候,Python會選擇產生與B同號的結果,因此 r 會是正數

所以q也就會隨著 r 變成多 -1

解決辦法可以直接轉str(BMR),f'{BMR[:-1]}.{BMR[-1]}0' 即可

 

詳細可以參考下方內容:

https://docs.python.org/3/faq/programming.html#why-does-22-10-return-3

 

為什麼 -22 // 10 會返回 -3 ?

這主要是為了讓 i % j 的正負與 j 一致,如果期望如此,且期望如下等式成立:

i == (i // j) * j + (i % j)

那麼整除就必須返回向下取整的結果。C 語言同樣要求保持這種一致性,於是編譯器在截斷 i // j 的結果時需要讓 i % j 的正負與 i 一致。

對於 i % j 來說 j 為負值的應用場景實際上是非常少的。 而 j 為正值的情況則非常多,並且實際上在所有情況下讓 i % j 的結果為 >= 0 會更有用處。 如果現在時間為 10 時,那麼 200 小時前應是幾時? -190 % 12 == 2 是有用處的;-190 % 12 == -10 則是會導致意外的漏洞。

Why does -22 // 10 return -3?

It’s primarily driven by the desire that i % j have the same sign as j. If you want that, and also want:

i == (i // j) * j + (i % j)

then integer division has to return the floor. C also requires that identity to hold, and then compilers that truncate i // j need to make i % j have the same sign as i.

There are few real use cases for i % j when j is negative. When j is positive, there are many, and in virtually all of them it’s more useful for i % j to be >= 0. If the clock says 10 now, what did it say 200 hours ago? -190 % 12 == 2 is useful; -190 % 12 == -10 is a bug waiting to bite.

 

 
ZeroJudge Forum