第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問題,去搜搜看,總會(huì)有你想問的

Java POI FormulaEvaluator 給出意外的浮點(diǎn)值

Java POI FormulaEvaluator 給出意外的浮點(diǎn)值

桃花長相依 2024-01-28 16:11:35
這是《Java 哲學(xué)》一書中的示例(請(qǐng)記住 FancyToy 擴(kuò)展了 Toy):Class<FancyToy> ftClass = FancyToy.class;Class<? super FancyToy> up = ftClass.getSuperclass(); //compilesClass<Toy> up = ftClass.getSuperclass(); //doesn't compile 在IDEA中嘗試了很多次,只是出現(xiàn)“不兼容類型”的消息。請(qǐng)給我一個(gè)提示,為什么我們不能僅使用泛型類型玩具?我正在使用 Java POI 庫讀取 Excel 文件,然后將其顯示在 HTML 表格中。Excel 文件非常簡單,只有 1 行 3 列:A1 單元格= 21.7 B1 單元格= 20.0 C1 單元格是一個(gè)公式單元格,其公式為 =(A1-B1)/B1,它具有自定義格式“百分比”,小數(shù)點(diǎn)后 0 位。Excel 將其值顯示為 9%。這是因?yàn)?1.7/20 在計(jì)算器上給出的結(jié)果是 0.085;當(dāng)它轉(zhuǎn)換為“百分比”格式時(shí),它會(huì)變成 8.5%,并且因?yàn)楦袷斤@示包含 0 位小數(shù),所以它會(huì)四舍五入到 9%,這就是 Excel 顯示的內(nèi)容。都好。然而,POI 將該值顯示為 8%。我觀察到 1.7/20 的計(jì)算結(jié)果是 0.084999999。由于上面應(yīng)用的百分比格式,它會(huì)轉(zhuǎn)換為 8.4999999%,并且由于小數(shù)點(diǎn)后 0 位,它會(huì)向下舍入為 8%。如何讓 POI 返還 9% 而不是 8%?這是代碼片段:String myFormat="0%";CreationHelper helper = wbWrapper.getWb().getCreationHelper();CellUtil.setCellStyleProperty(cell, CellUtil.DATA_FORMAT,helper.createDataFormat().getFormat(myFormat));String val = dataFormatter.formatCellValue(cell, evaluator);這里 evaluator 是 org.apache.poi.ss.usermodel.FormulaEvaluator 的實(shí)例,dataFormatter 是 org.apache.poi.ss.usermodel.DataFormatter 的實(shí)例當(dāng)我打印變量“val”時(shí),它返回 8%,而不是 Excel 中顯示的值 (9%)。
查看完整描述

1 回答

?
茅侃侃

TA貢獻(xiàn)1842條經(jīng)驗(yàn) 獲得超21個(gè)贊

你的觀察是正確的。該問題的出現(xiàn)是因?yàn)橐话愕母↑c(diǎn)問題??梢院唵蔚乇硎緸椋?/p>


...

System.out.println(1.7/20.0); //0.08499999999999999

System.out.println((21.7-20.0)/20.0); //0.08499999999999996

...

如您所見,雙精度值 1.7 除以雙精度值 20.0 得到 0.08499999999999999。這很好,因?yàn)槭褂?時(shí)該值將被視為 0.085 DecimalFormat。但更復(fù)雜的方程 (21.7-20.0)/20.0 結(jié)果為 0.08499999999999996。這顯然低于 0.085。


Excel嘗試通過浮點(diǎn)值的附加規(guī)則來解決這些問題。它始終僅使用浮點(diǎn)值的 15 位有效十進(jìn)制數(shù)字。類似的事情也是如此Excel:


...

BigDecimal bd = new BigDecimal((21.7-20.0)/20.0);

System.out.println(bd.round(new MathContext(15)).doubleValue()); //0.085

...

apache poi's FormulaEvaluator和 it's 的DataFormatter行為都不像這Excel一點(diǎn)。這就是差異的原因。


人們可以擁有一個(gè)自己的,與/org/apache/poi/ss/usermodel/DataFormatter.javaMyDataFormatter的唯一區(qū)別是:


...

    private String getFormattedNumberString(Cell cell, ConditionalFormattingEvaluator cfEvaluator) {

        if (cell == null) {

            return null;

        }

        Format numberFormat = getFormat(cell, cfEvaluator);


        double d = cell.getNumericCellValue();

        java.math.BigDecimal bd = new java.math.BigDecimal(d);

        d = bd.round(new java.math.MathContext(15)).doubleValue();


        if (numberFormat == null) {

            return String.valueOf(d);

        }

        String formatted = numberFormat.format(Double.valueOf(d));

        return formatted.replaceFirst("E(\\d)", "E+$1"); // to match Excel's E-notation

    }

...

然后使用 thatMyDataFormatter而不是DataFormatter會(huì)更符合 的Excel行為。


例子:


import java.io.FileOutputStream;


import org.apache.poi.ss.usermodel.*;

import org.apache.poi.ss.util.*;

import org.apache.poi.xssf.usermodel.XSSFWorkbook;


class CreateExcelEvaluateFormula {


 public static void main(String[] args) throws Exception {


  Workbook workbook  = new XSSFWorkbook();

  CreationHelper creationHelper = workbook.getCreationHelper();

  FormulaEvaluator formulaEvaluator = creationHelper.createFormulaEvaluator();


  Sheet sheet = workbook.createSheet();

  Row row = sheet.createRow(0);

  Cell cell = row.createCell(0); cell.setCellValue(21.7);

  cell = row.createCell(1); cell.setCellValue(20.0);


  cell = row.createCell(2); cell.setCellFormula("(A1-B1)/B1");

  formulaEvaluator.evaluateFormulaCell(cell); 

  double d = cell.getNumericCellValue();

System.out.println(d); //0.08499999999999996


  MyDataFormatter dataFormatter = new MyDataFormatter();


  String myFormat="0%";

  CellUtil.setCellStyleProperty(cell, CellUtil.DATA_FORMAT, creationHelper.createDataFormat().getFormat(myFormat));

  String val = dataFormatter.formatCellValue(cell, formulaEvaluator);

  System.out.println(val); //9%


  FileOutputStream out = new FileOutputStream("Excel.xlsx");

  workbook.write(out);

  out.close();

  workbook.close();


 }

}


查看完整回答
反對(duì) 回復(fù) 2024-01-28
  • 1 回答
  • 0 關(guān)注
  • 314 瀏覽

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)