求“result=60-x*10/y”的值,x,y是變量。要求四舍五入。
請大家幫忙看看。
網友評論:to LZ:
要想嚴格使用四舍五入,必須采用浮點運算。
網友評論:
我要求的就是整型。
你的
計算看上去很復雜,我不是很明白。寫程序時具體如何操作呢?
另外,你在“7樓”的答案不是很簡潔嗎,為什么現在換了一種計算方式呢?
你可否幫我看看我在17樓的做法是否妥當?
謝謝!
網友評論:
必須嚴格使用四舍五入。不能使用浮點數(有些MCU不支持浮點數運算,或者考慮到速度、程序空間、省電等因素,盡量避免使用浮點數)。
我在“17樓”寫出我的做法。我想知道還有沒有更簡單的方法。
網友評論:
你不是對7樓表達式的正確性表示懷疑嘛, 我23樓寫的就是對7樓表達式的解釋
7樓表達式可以分解成
result=60-(x*20+y-1)/(2*y)=60-x*20/(2*y)-(y-1)/(2*y)
其中x*20/(2*y)這項可以表示為a+b/(2*y), 這里的a是結果的整數部分, b是余數
所以上面的表達式可以改寫為:
result=60-a-b/(2*y)-(y-1)/(2*y)=60-a-(b+y-1)/(2*y)
最終的結果就是
result=60-a, 當b<=y時, 也就是x*10/y的小數部分<=0.5時, 結果舍入
result=60-a-1, 當b>y時, 也就是x*10/y的小數部分>0.5時, 結果舍去
當然要保證結果的正確性, 中間計算時需要保證不會發生溢出
網友評論:呵呵, result=60-(x*20+y-1)/(2*y)就是LZ需要的嚴格四舍五入的結果
網友評論:LZ的這個問題本身是個偽命題。
lz要求求result的結果,并對該結果進行四舍五入,那么2樓的解法就是正確解法。
如果需要考慮到所有的整型計算帶來的丟位問題,那只有使用浮點,其它都別想了。
另外,你給出的60-23*10/9=34.44444444444444?本身也是偽命題,23*10/9=25.55,因為整型丟位問題,就變成了25,不會自動4舍5入為26的,而你自己在做這個計算時候,卻把它幻化成了26,結果自然就不對,正確應該是60-25=35,而并不是你所理解的34。
而你在求600-23*100/9的時候又進行了取整做減法,所以,問題是你自己兩者計算條件不對等造成的。
網友評論:攪一下渾水,俺也來一個:
result=600-x*100/y;
result=(result+6)/10;
2L之所以被LZ抓到bug,無非是LZ沒有說明是最終結果四舍五入,而中間計算過程要保留浮點數,這樣一來,2L的公式就沒有處理0.5這個零界值的問題
所以只要解決后面計算過程五舍六入,即可保證整體結果四舍五入。。。。。
麻煩LZ也幫俺驗證一下這個公式,是不是也有蟲子....
網友評論:攪一下渾水,俺也來一個:
result=600-x*100/y;
result=(result+6)/10;
2L之所以被LZ抓到bug,無非是LZ沒有說明是最終結果四舍五入,而中間計算過程要保留浮點數,這樣一來,2L的公式就沒有處理0.5這個零界值的問題 ...
不亦心 發表于 2010-10-9 08:44
只要按照LZ那種互相矛盾的算法,這也是不成立的。
例如:x=496,y=100,則即不成立。
網友評論:
更正32L
result=(x*100/y+6)/10;
result=60-result;
貌似這樣就可以了
先把后面的五舍六入,再作減法,才能保證整體結果四舍五入
網友評論:更正32L
result=(x*100/y+6)/10;
result=60-result;
貌似這樣就可以了
先把后面的五舍六入,再作減法,才能保證整體結果四舍五入
不亦心 發表于 2010-10-9 09:09
還是不成立,具體就不說了。
網友評論:四舍五入應該是逢五進1吧
網友評論:2樓yewuyi方法是可行的,難道LZ的x,y不是整形,如果是整形的話,計算機計算x*100/y是要取整的,
網友評論:to yewuyi:
謝謝你關注這個帖子。
我發這個帖子是想和大家討論技術問題。請不要再用“見鬼了”,“LZ腦子犯暈了”這樣的字眼。
尊重別人即是尊重自己。 ...
fushaobing 發表于 2010-10-8 17:58
你竟然能和‘尊重別人即是尊重自己’結合起來,I 服了 you !
沒有自尊心是不對的,過于強烈的自尊心只會導致自己經常急火攻心。
網友評論:這種帖子好
網友評論:二位,蛋定...啊,
網友評論:2樓yewuyi方法是可行的,難道LZ的x,y不是整形,如果是整形的話,計算機計算x*100/y是要取整的,
hwwyhy 發表于 2010-10-9 10:24
要按照LZ那種互相矛盾的要求來說,2樓的方法確實是有問題的。
其實,這個問題本身就有一定的悖論,4舍5入是有前提的,無前提的4舍5入也是有問題的,例如0.499,你說這個值多少是多少?
無前提的4舍5入的話,則可以是1,也可以是0.5,還可能是0.4
網友評論:恩,是的,這就要求一個精度了,精度越高如果不用浮點的話,計算量就要越大
網友評論:這是一個復合運算的誤差傳遞問題。
無論采用什么算法,只要中間過程有舍有入,其運算結果的最后一位必然都是可疑的。
采用半進位方法提高運算精度,一般只針對單一運算。
有一個辦法可以提高復合運算的精度,就是將所有的源數據都乘以適當的倍數,最后的運算結果做除以相同的因子后做取舍,不過這也僅是0.51、0.501、0.500。。。001之間的區別。比如說34.49999999仍然避免不了被判讀為34的結果。因此這種方法只是減小了判別出錯的幾率,可是相應的代價也是相當大的。
網友評論:to yewuyi:
你沒有看懂我的要求,解決不了問題,就不要說什么“偽命題”了?
我后面說過了,“60-23*10/9=34.44444444444444”是在草稿紙上的驗算過程,不是在MCU上的執行過程。
當x=23,y=9時,正確結果應該是34。如果你的程序計算結果是35,就是不對的。不知道你能不能理解這一點。
“32樓”說到了點子上。
不知道yewuyi有沒有看懂“32樓”的話。
如果2樓的答案是正確的,我根本不會發這個帖子出來。
這個問題我不是沒有解決,我在17樓給出了我的做法。只是我覺得這個問題有點意思,所以拿出來和大家討論一下。
老實說,對于說話不經過大腦,卻三番兩次口出不遜的人,我的自尊心真的受到了傷害。
網友評論:
謝謝你。你說到問題的點子上了。我在17樓的處理就是專門把“0.5”這種情況找出來特別對待。
至于你在“34樓”的公式,請給我一點時間驗算。
網友評論:result=60-x*10/y
我覺得這個四舍五入的問題之所以特殊,根本原因在于一個未知的"x*10/y"處于減數的位置。
如果題目改成"result=60+x*10/y"(要求四舍五入),則不會有任何問題。
網友評論:2樓yewuyi方法是可行的,難道LZ的x,y不是整形,如果是整形的話,計算機計算x*100/y是要取整的,
hwwyhy 發表于 2010-10-9 10:24
2樓的方法大多數情況下不會出錯,但在某些情況下會出錯(比如x=23,y=9)。
我的第一反應就是使用2樓的方法,但是很可惜,不行。
如果2樓的方法可行,就不會有這個帖子出現。
沒錯,x,y是整型,計算機處理時會取整,會造成數據丟失。所以,我們知道了這一點,就要想辦法避免這種數據丟失。這也是這個帖子要解決的問題。
網友評論:
“比如說34.49999999仍然避免不了被判讀為34的結果。”
如果result=34.49999999,那么"34"就是我要的結果。這有什么問題嗎?四舍五入指的當然是最近的那個小數位了,至于別的位有幾個9,是不理睬的。
網友評論:to fushaobing:
暈,你真的用窮舉法驗證?我前面已經用數學的方法證明了結果是正確的了
網友評論:LS,我很好奇,你的那個公式是怎么想到的
我數學忒差,要不是你給出推導過程,死活也看不明白
網友評論:
y是整數時,(y-1)/(2*y)是<0.5的以2*y為模能表達的最大的數
通常所謂的四舍五入是指小數部分>=0.5時向數軸的+無窮大進位,所以如果結果是一個負數,比如-3.5,
四舍五入后應該是-3,而不是-4
網友評論:LZ,俺的那個你不用試了,和2L的根本就沒有區別,唯一改變的是把臨界點從0.5改成0.4了,暈倒
我都不知道自己怎么想的。。。。
貌似ZALIN的算式可用
網友評論:確實關乎變量的類型:整型或浮點型,有符號或無符號等。
網友評論:這個帖子不錯,學習了,更是受教育啊!看來以后要常來了
網友評論:to ZALIN:
我的題目是從一個具體的問題抽象出來的,如果用窮舉,是不需要從0x01~0xffffffff全部試完的。我需要驗證的范圍其實很小。
我準備寫一個C程序來窮舉。不會太麻煩的。
不是不相信你對公式的解釋,老實說,我還是沒看懂(汗顏)。不過即使看懂了,我還是會驗證一下。做技術的還是謹慎一點的好。
網友評論:result=60-float(x)*10/y;估計很耗時,嘿嘿
網友評論:to 不亦心:
你看懂“ZALIN”的推導過程了嗎?哈哈,看來我要努力了。
網友評論:謝謝大家的關注。
有朋友說這個問題必須使用浮點數才能解決。未免有點牽強。
我們總不能為了一個四舍五入的問題,對老板或者客戶說,“問題很難辦。除非換一個支持浮點數運算的MCU,或者不要求四舍五入的結果是百分百正確。”
網友評論:我是這樣解決的。(已經用窮舉的方法驗證過了)
if ( (((x*100)%y)==0) && ((((x*100)/y)%10)==5) )
{
//do not round
x=x*10/y;
}
else
{
// round
x=x*100/y;
x=(x+5)/10;
}
if (x<60) result=60-x;
...
網友評論:我的想法很簡單,把x*10/y的小數部分為“0.5000000000(后面全部是0)”的情況拿出來特別對待。
網友評論:ZALIN的算法,應該是對整數除法運算中取整誤差的一種修正方法,用修正一個 (y-1)/2*y(小于0.5的一個最大值)的小數部分,使舍去的小數部分大于等于0.5的自動進位為1。
不知道自己的想法是不是正確的?
網友評論:你簡直就是一個SB...
滾你媽蛋..
網友評論:to ZALIN:
你的公式是準確的!
我已經用窮舉的方法試過了,我需要的約兩萬組數據全部能得出準確結果。
謝謝你!
網友評論:to ZALIN:
你的公式是正確的!
我已經用窮舉的方法試過了。我需要的約兩萬種情況全部能得出正確結果。
謝謝你!
網友評論:你簡直就是一個SB...
滾你媽蛋..
yewuyi 發表于 2010-10-10 16:50
急火攻心了?
此時此刻,你做人的水準和做事的水準我已經知道了。
本來,熱愛技術的人在一起討論技術問題是一件很開心的事。懂與不懂,錯與對又有什么關系?大家討論分析一下,總會明白的。何必三番兩次出言不遜,現在連臟話都罵出來了?
雖然是在網絡上,但人與人之間的尊重跟在現實生活中沒有區別。
網友評論:急火攻心了?
此時此刻,你做人的水準和做事的水準我已經知道了。
本來,熱愛技術的人在一起討論技術問題是一件很開心的事。懂與不懂,錯與對又有什么關系?大家討論分析一下,總會明白的。何必三番兩次出言不遜 ...
fushaobing 發表于 2010-10-11 13:44
是你這SB先罵老子的。
只要不是SB都應該知道‘見鬼了’,‘犯暈了’基本是一些中性詞語。
網友評論:像你這么囂張的俺見多了,別以為俺不會開口罵人。。。
網友評論:俺好心給你回答問題,你TMD不感謝半句,反而攻擊老子,你以為俺欺負是吧。。。
你5樓的計算本來是就矛盾的,我在隨后的帖子中已經分析的清清楚楚,你自己沒本事把問題描述清楚,關別人屁事情。
網友評論:總結(結貼)
題目:求“result=60-x*10/y”的值,要求四舍五入。所有變量都為長整型。(不可以使用浮點運算)
7樓給出的答案“result=60-(x*20+y-1)/(2*y)”能得到百分百正確的結果,而且非常簡潔。
謝謝“ZALIN”!
我自己的做法如下。
if ( (((x*100)%y)==0) && ((((x*100)/y)%10)==5) )
{
x=x*10/y;
}
else
{
x=x*100/y;
x=(x+5)/10;
}
if (x<60) result=60-x;
...
雖然可行,但過于繁瑣。
謝謝所有關注或回復此貼的人!謝謝你們的意見!
此貼對任何人引起的任何不快,我在這里表示歉意。那并不是我想看到的。
2010-10-11
網友評論:路過,學習了。
網友評論:我完整的看了所有的評論,其實是LZ和2樓對問題的理解有偏差,原因32樓已經說了
這里對2樓的算法做一下改進就行了,如下:
result =( (600*y-x*100)/y + 5)/10
應該說兩位高手說的都沒錯!
再強調一下2樓的算法對解四舍五入沒有問題
網友評論:
70樓是錯誤的
網友評論:
謝謝你的耐心和指教!
我驗算了你的公式,全部能得出正確結果。可否請教一下你的思路?為什么你那樣一改,就ok了?
另外,當客戶將公式“result=60-x*10/y”(要求四舍五入)提供給我之后,他將怎樣驗收我的軟件呢?他不外乎就是通過Windows系統附件里面的“計算器”,或者用Excel制作一個表格來驗算。客戶不管計算過程,只要正確結果。
因此,對于本貼的問題,2樓的算法達不到要求(大部分正確,小部分不正確)。我這樣說,不知道您是否認同?
網友評論:
補充一點。
你說“再強調一下2樓的算法對解四舍五入沒有問題”,我有不同的意見。我的看法是,如果“x*10/y”前面是一個加號,那么2樓的算法完全正確。如果“x*10/y”前面是一個減號(即為負數),則不可以這樣處理。
你怎么看?想聽聽您的意見。
網友評論:
哈哈,有趣
我驗算了一下
基本正確
網友評論:2樓的做法是對(10*x/y)這個項做了四舍五入,而我的做法是對(60-10*x/y)做四舍五入,這就是根本的區別。所以我說2樓關于四舍五入的算法是沒錯的。
另外這所以會有10*x/y前面是+運算可以,對-運算就不成立,是因為C語言對整形數的運算規則里小數點后面都是舍去的。所以(10*x/y)這項整形計算值<用浮點型運算值
另外我對7樓的算法也很感興趣,試圖去證明它的正確性,(y-1/2y)<0.5,最接近0.5的有效表達值這是成立的。
共同研究,呵呵。也請原創作者證明一下,好比說用數學歸納法。窮舉不是個科學的驗證方法
網友評論:樓主你可以把問題看成是(60-(xx.000(純整數)+0.xxx(純小數)))這樣你就明白為什么前面是+就行是-就有可能出錯
網友評論:
關于(y-1)/2y<0.5并且最接近0.5,因為y/2y=0.5,而y-1是小于y的最大整數,顯而易見可以得出前述結論
你在72樓的算式是把LZ的算式轉換成了一個‘正’表達式,所以可以適用+0.5再取整的方法,
不過可以簡化成:result =(60*y-x*10+y/2)/y,60*y>=x*10
我們可以歸納出普遍的整數運算的四舍五入的方法:
形如:result=a+b/c,四舍五入可以表示為:result=a+(b+c/2)/c
形如:result=a-b/c,四舍五入可以表示為:result=a-(2b+c-1)/2c 或result=a-(b+(c-1)/2)/c
上述算式中的除法是整數運算,也就是取整數,丟棄余數。
如果一個算式中有多于一個的除法表達式,可以合并成一個除法表達式后再使用上述方法
網友評論:to 雨下楓:
謝謝你的解釋!
感覺很不可思議!我為什么就想不到呢?哈哈。
7樓后來也給出了推導過程,麻煩你自己找一下。
另外,我覺得對(10*x/y)這個項做四舍五入應該這樣寫:result=60-(x*20+y)/(2*y).
這與2樓的“result =( 600-x*100/y + 5)/10”還是有很大區別的。我剛才驗算了約兩萬組數據,前者產生18個錯誤,后者產生457個錯誤。
網友評論:to ZALIN
可能我沒表達清楚,我是想證明為什么對任意x/y(x,y為整數),做四舍五入可以用(2x+y-1)/2y來解決呢?
想通過數學的方法去證明它
網友評論:不好意思打擾了,我看明白了
網友評論:to ZALIN:
你歸納得很精彩!佩服!
謝謝你!
網友評論:如果運算的數字不是太大的話,用10樓的方法
盡量把數放大,別超出范圍就行。
網友評論:ws
網友評論:該覺樓主的命題有問題:
1.x,y,result的數據類型沒有交代;
2.四舍五入是針對哪一位,沒有交代;