日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > c/c++ >内容正文

c/c++

浮点高精求和(洛谷P2393题题解,弃坑Java拥抱C++)

發(fā)布時(shí)間:2025/3/15 c/c++ 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 浮点高精求和(洛谷P2393题题解,弃坑Java拥抱C++) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

題目要求

P2393題目鏈接

分析

這題實(shí)則是變態(tài)的大浮點(diǎn)加法,眾所周知的是浮點(diǎn)不精確,按照IEEE754來(lái)。
原先使用Java寫(xiě)的,但下面分析一下為什么不能用Java寫(xiě)。

這代碼本來(lái)是這么寫(xiě)的:

import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);double sum = 0.0;String[] array = scanner.nextLine().trim().split("\\s+");scanner.close();for (String s : array) {sum += 1000000 * Double.parseDouble(s);}System.out.printf("%.5f", sum/1000000);} }

但結(jié)果是這樣的:

你們敢想象為什么RE?我下了數(shù)據(jù),是空文件,連換行符都沒(méi)有……
我原本以為數(shù)據(jù)錯(cuò)了,可能有換行符的,就加了一個(gè)特判:

import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);double sum = 0.0;String line = scanner.nextLine();if ("".equals(line)) {System.out.println("0.00000");return;}String[] array = line.trim().split("\\s+");scanner.close();for (String s : array) {sum += 1000000 * Double.parseDouble(s);}System.out.printf("%.5f", sum/1000000);} }

結(jié)果一樣的,真的惡心啊。
你用nextLine()或者readLine()沒(méi)用的,根本不行。
用任何Scanner都不能過(guò),只能用BufferedReader,但也沒(méi)什么頭緒,畢竟BufferedReader一般來(lái)說(shuō)只能讀取一行或者一個(gè)字符,都不合適。
想了很久,就琢磨出一個(gè)騷方法:

import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader;public class Main {public strictfp static void main(String[] args) throws IOException {BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));double sum = 0.0;int firstRead = reader.read();if (firstRead == -1) {System.out.println("0.00000");return;}firstRead -= 48;String line = firstRead + reader.readLine();String[] array = line.trim().split("\\s+");reader.close();for (String s : array) {sum += 1000000 * Double.parseDouble(s);}System.out.printf("%.5f", sum/1000000);} }

沒(méi)錯(cuò),先讀首字符,如果沒(méi)有就拜拜,打印0.00000,否則就拼接起來(lái)唄……
只過(guò)了第一個(gè),后5個(gè)還是WA:

下了一個(gè)數(shù)據(jù)6,震驚,被惡心到了,double拼起來(lái)必定不精確啊,一看確實(shí),誤差挺大。

我后來(lái)加上了strictfp關(guān)鍵詞,發(fā)現(xiàn)對(duì)double無(wú)效。(這個(gè)詞研究不深,但測(cè)過(guò)多次,盲猜是讓float按照IEEE754算,對(duì)double沒(méi)啥大用……)

突然靈機(jī)一動(dòng),高精?我上BigDecimal吧,高精沒(méi)毛病:

import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.math.BigDecimal; import java.math.RoundingMode;public class Main {public strictfp static void main(String[] args) throws IOException {BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));BigDecimal sum = new BigDecimal(0).setScale(5, RoundingMode.HALF_EVEN);;int firstRead = reader.read();if (firstRead == -1) {System.out.println("0.00000");return;}firstRead -= 48;String line = firstRead + reader.readLine();String[] array = line.trim().split("\\s+");reader.close();for (String s : array) {sum = sum.add(new BigDecimal(Double.parseDouble(s)));}System.out.printf("%.5f", sum);} }

結(jié)果只能說(shuō)略有改觀吧:

測(cè)試點(diǎn)6和8過(guò)不去的,對(duì)比發(fā)現(xiàn)我們的BigDecimal算的過(guò)于精確了……比給的answer精確……
我瞬間心態(tài)爆炸……
讀到這里您也能想到我為了各種測(cè)試畫(huà)了多少時(shí)間和精力吧,居然不是不精確就是過(guò)精確。
偏偏Java沒(méi)有 long double 這回事,枯萎……

然后我棄坑Java,拾起C++,十行以?xún)?nèi)秒了這題。。。

一句題外話(huà)是:性能差距過(guò)大。

提示:洛谷的OJ基本面向中學(xué)信息學(xué)競(jìng)賽,所以C++是王道,你用Java人家不理你的,見(jiàn)好就收即可,嗯……

AC代碼(C++語(yǔ)言描述)

#include<cstdio> long double result, temp; int main() {while((scanf("%Lf", &temp)) != EOF) {result += temp * 1000000;}printf("%.5Lf", result / 1000000);return 0; } 創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

總結(jié)

以上是生活随笔為你收集整理的浮点高精求和(洛谷P2393题题解,弃坑Java拥抱C++)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。