mirror of
https://gitee.com/dromara/hutool.git
synced 2025-05-04 04:37:59 +08:00
fix float bug
This commit is contained in:
parent
b5145a0bac
commit
838a2c45a6
@ -1063,28 +1063,28 @@ public class NumberUtil {
|
|||||||
* 格式化double<br>
|
* 格式化double<br>
|
||||||
* 对 {@link DecimalFormat} 做封装<br>
|
* 对 {@link DecimalFormat} 做封装<br>
|
||||||
*
|
*
|
||||||
* @param pattern 格式 格式中主要以 # 和 0 两种占位符号来指定数字长度。0 表示如果位数不足则以 0 填充,# 表示只要有可能就把数字拉上这个位置。<br>
|
* @param pattern 格式 格式中主要以 # 和 0 两种占位符号来指定数字长度。0 表示如果位数不足则以 0 填充,# 表示只要有可能就把数字拉上这个位置。<br>
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>0 =》 取一位整数</li>
|
* <li>0 =》 取一位整数</li>
|
||||||
* <li>0.00 =》 取一位整数和两位小数</li>
|
* <li>0.00 =》 取一位整数和两位小数</li>
|
||||||
* <li>00.000 =》 取两位整数和三位小数</li>
|
* <li>00.000 =》 取两位整数和三位小数</li>
|
||||||
* <li># =》 取所有整数部分</li>
|
* <li># =》 取所有整数部分</li>
|
||||||
* <li>#.##% =》 以百分比方式计数,并取两位小数</li>
|
* <li>#.##% =》 以百分比方式计数,并取两位小数</li>
|
||||||
* <li>#.#####E0 =》 显示为科学计数法,并取五位小数</li>
|
* <li>#.#####E0 =》 显示为科学计数法,并取五位小数</li>
|
||||||
* <li>,### =》 每三位以逗号进行分隔,例如:299,792,458</li>
|
* <li>,### =》 每三位以逗号进行分隔,例如:299,792,458</li>
|
||||||
* <li>光速大小为每秒,###米 =》 将格式嵌入文本</li>
|
* <li>光速大小为每秒,###米 =》 将格式嵌入文本</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* @param value 值,支持BigDecimal、BigInteger、Number等类型
|
* @param value 值,支持BigDecimal、BigInteger、Number等类型
|
||||||
* @param roundingMode 保留小数的方式枚举
|
* @param roundingMode 保留小数的方式枚举
|
||||||
* @return 格式化后的值
|
* @return 格式化后的值
|
||||||
* @since 5.6.5
|
* @since 5.6.5
|
||||||
*/
|
*/
|
||||||
public static String decimalFormat(String pattern, Object value, RoundingMode roundingMode) {
|
public static String decimalFormat(String pattern, Object value, RoundingMode roundingMode) {
|
||||||
if(value instanceof Number){
|
if (value instanceof Number) {
|
||||||
Assert.isTrue(isValidNumber((Number) value), "value is NaN or Infinite!");
|
Assert.isTrue(isValidNumber((Number) value), "value is NaN or Infinite!");
|
||||||
}
|
}
|
||||||
final DecimalFormat decimalFormat = new DecimalFormat(pattern);
|
final DecimalFormat decimalFormat = new DecimalFormat(pattern);
|
||||||
if(null != roundingMode){
|
if (null != roundingMode) {
|
||||||
decimalFormat.setRoundingMode(roundingMode);
|
decimalFormat.setRoundingMode(roundingMode);
|
||||||
}
|
}
|
||||||
return decimalFormat.format(value);
|
return decimalFormat.format(value);
|
||||||
@ -1472,7 +1472,7 @@ public class NumberUtil {
|
|||||||
* @since 5.6.0
|
* @since 5.6.0
|
||||||
*/
|
*/
|
||||||
public static BigInteger factorial(BigInteger n) {
|
public static BigInteger factorial(BigInteger n) {
|
||||||
if(n.equals(BigInteger.ZERO)){
|
if (n.equals(BigInteger.ZERO)) {
|
||||||
return BigInteger.ONE;
|
return BigInteger.ONE;
|
||||||
}
|
}
|
||||||
return factorial(n, BigInteger.ZERO);
|
return factorial(n, BigInteger.ZERO);
|
||||||
@ -1492,21 +1492,21 @@ public class NumberUtil {
|
|||||||
public static BigInteger factorial(BigInteger start, BigInteger end) {
|
public static BigInteger factorial(BigInteger start, BigInteger end) {
|
||||||
Assert.notNull(start, "Factorial start must be not null!");
|
Assert.notNull(start, "Factorial start must be not null!");
|
||||||
Assert.notNull(end, "Factorial end must be not null!");
|
Assert.notNull(end, "Factorial end must be not null!");
|
||||||
if(start.compareTo(BigInteger.ZERO) < 0 || end.compareTo(BigInteger.ZERO) < 0){
|
if (start.compareTo(BigInteger.ZERO) < 0 || end.compareTo(BigInteger.ZERO) < 0) {
|
||||||
throw new IllegalArgumentException(StrUtil.format("Factorial start and end both must be > 0, but got start={}, end={}", start, end));
|
throw new IllegalArgumentException(StrUtil.format("Factorial start and end both must be > 0, but got start={}, end={}", start, end));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (start.equals(BigInteger.ZERO)){
|
if (start.equals(BigInteger.ZERO)) {
|
||||||
start = BigInteger.ONE;
|
start = BigInteger.ONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(end.compareTo(BigInteger.ONE) < 0){
|
if (end.compareTo(BigInteger.ONE) < 0) {
|
||||||
end = BigInteger.ONE;
|
end = BigInteger.ONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BigInteger result = start;
|
BigInteger result = start;
|
||||||
end = end.add(BigInteger.ONE);
|
end = end.add(BigInteger.ONE);
|
||||||
while(start.compareTo(end) > 0) {
|
while (start.compareTo(end) > 0) {
|
||||||
start = start.subtract(BigInteger.ONE);
|
start = start.subtract(BigInteger.ONE);
|
||||||
result = result.multiply(start);
|
result = result.multiply(start);
|
||||||
}
|
}
|
||||||
@ -2116,7 +2116,7 @@ public class NumberUtil {
|
|||||||
*/
|
*/
|
||||||
public static String toStr(BigDecimal bigDecimal, boolean isStripTrailingZeros) {
|
public static String toStr(BigDecimal bigDecimal, boolean isStripTrailingZeros) {
|
||||||
Assert.notNull(bigDecimal, "BigDecimal is null !");
|
Assert.notNull(bigDecimal, "BigDecimal is null !");
|
||||||
if(isStripTrailingZeros){
|
if (isStripTrailingZeros) {
|
||||||
bigDecimal = bigDecimal.stripTrailingZeros();
|
bigDecimal = bigDecimal.stripTrailingZeros();
|
||||||
}
|
}
|
||||||
return bigDecimal.toPlainString();
|
return bigDecimal.toPlainString();
|
||||||
@ -2669,10 +2669,26 @@ public class NumberUtil {
|
|||||||
* @return 结果
|
* @return 结果
|
||||||
* @since 5.7.6
|
* @since 5.7.6
|
||||||
*/
|
*/
|
||||||
public static double calculate(String expression){
|
public static double calculate(String expression) {
|
||||||
return Calculator.conversion(expression);
|
return Calculator.conversion(expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number值转换为double<br>
|
||||||
|
* float强制转换存在精度问题,此方法避免精度丢失
|
||||||
|
*
|
||||||
|
* @param value 被转换的float值
|
||||||
|
* @return double值
|
||||||
|
* @since 5.7.8
|
||||||
|
*/
|
||||||
|
public static double toDouble(Number value) {
|
||||||
|
if(value instanceof Float){
|
||||||
|
return Double.parseDouble(value.toString());
|
||||||
|
}else{
|
||||||
|
return value.doubleValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------- Private method start
|
// ------------------------------------------------------------------------------------------- Private method start
|
||||||
private static int mathSubNode(int selectNum, int minNum) {
|
private static int mathSubNode(int selectNum, int minNum) {
|
||||||
if (selectNum == minNum) {
|
if (selectNum == minNum) {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package cn.hutool.poi.excel.cell.setters;
|
package cn.hutool.poi.excel.cell.setters;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.NumberUtil;
|
||||||
import cn.hutool.poi.excel.cell.CellSetter;
|
import cn.hutool.poi.excel.cell.CellSetter;
|
||||||
import org.apache.poi.ss.usermodel.Cell;
|
import org.apache.poi.ss.usermodel.Cell;
|
||||||
|
|
||||||
@ -26,10 +27,6 @@ public class NumberCellSetter implements CellSetter {
|
|||||||
public void setValue(Cell cell) {
|
public void setValue(Cell cell) {
|
||||||
// issue https://gitee.com/dromara/hutool/issues/I43U9G
|
// issue https://gitee.com/dromara/hutool/issues/I43U9G
|
||||||
// 避免float到double的精度问题
|
// 避免float到double的精度问题
|
||||||
if (value instanceof Float) {
|
cell.setCellValue(NumberUtil.toDouble(value));
|
||||||
cell.setCellValue(value.floatValue());
|
|
||||||
} else {
|
|
||||||
cell.setCellValue(value.doubleValue());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -721,4 +721,16 @@ public class ExcelWriteTest {
|
|||||||
|
|
||||||
writer.close();
|
writer.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Ignore
|
||||||
|
public void writeFloatTest(){
|
||||||
|
//issue https://gitee.com/dromara/hutool/issues/I43U9G
|
||||||
|
String path = "d:/test/floatTest.xlsx";
|
||||||
|
FileUtil.del(path);
|
||||||
|
|
||||||
|
final ExcelWriter writer = ExcelUtil.getWriter(path);
|
||||||
|
writer.writeRow(ListUtil.of(22.9f));
|
||||||
|
writer.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user