Java 数据格式化&小数点后保留指定位数
Posted ZSYL
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 数据格式化&小数点后保留指定位数相关的知识,希望对你有一定的参考价值。
小数点后保留指定n位数
DecimalFormat
使用 DecimalFormat,但是只能保留指定位数.
DecimalFormat d = new DecimalFormat("0.000");
double x = 3.45125;
System.out.println(d.format(x)); // 3.451
参考上篇博客 详解数字格式化
NumberFormat
public static String format(double value) {
// 获取实例对象
NumberFormat nf = NumberFormat.getNumberInstance();
nf.setMaximumFractionDigits(2);
/*
* setMinimumFractionDigits设置成2
*
* 如果不这么做,那么当value的值是100.00的时候返回100
*
* 而不是100.00
*/
nf.setMinimumFractionDigits(2);
nf.setRoundingMode(RoundingMode.HALF_UP);
/*
* 如果想输出的格式用逗号隔开,可以设置成true
*/
nf.setGroupingUsed(false);
return nf.format(value);
}
Formatter
java.util.Formatter
public static String format(double value) {
/*
* %.2f % 表示 小数点前任意位数 2 表示两位小数 格式后的结果为 f 表示浮点型
*/
return new Formatter().format("%.2f", value).toString();
}
String.format
String.format 作为文本处理工具,为我们提供强大而丰富的字符串格式化功能。
常见使用方式:
public static String format5(double value) {
return String.format("%.2f", value).toString();
}
占位符格式为:
%[index$][标识]*[最小宽度][.精度]转换符
可用标识符:
- -:在最小宽度内左对齐,不可以与0标识一起使用。
- 0:若内容长度不足最小宽度,则在左边用0来填充。
- #:对8进制和16进制,8进制前添加一个0,16进制前添加0x。
- +:结果总包含一个+或-号。
- 空格:正数前加空格,负数前加-号。
- ,:只用与十进制,每3位数字间用,分隔。
- (:若结果为负数,则用括号括住,且不显示符号。
可用转换符:
b,布尔类型,只要实参为非false的布尔类型,均格式化为字符串true,否则为字符串false。
n,平台独立的换行符, 也可通过System.getProperty(“line.separator”)获取。
f,浮点数型(十进制)。显示9位有效数字,且会进行四舍五入。如99.99。
a,浮点数型(十六进制)。
e,指数类型。如 9.38e+5。
g,浮点数型(比%f,%a 长度短些,显示6位有效数字,且会进行四舍五入)
实例展示:
// 测试代码
double num = 123.456789;
System.out.print(String.format("%f %n", num)); // %f:默认显示9位有效数字,且会进行四舍五入。%n:默认换行,123.456790
System.out.print(String.format("%a %n", num)); // %a:浮点数型(十六进制),0x1.edd3c0bb46929p6
System.out.print(String.format("%g %n", num)); // %g:浮点数型(比%f,%a长度短些,显示6位有效数字,且会进行四舍五入),123.457
// 保留小数点后位
System.out.println(String.format("%.2f", num)); // 123.46
// 左对齐
int n = 3;
// 6位右对齐,不足六位补0
System.out.println(String.format("%06d", n)); // 000003
// 6位右对齐,不足六位补空格
System.out.println(String.format("%6d", n)); // 3
// 6位左对齐,不足六位补空格
System.out.println(String.format("%-6d", n)); // 3
结果如下
printf()
C语言中 printf 函数使用很方便,很高兴Java中也可以使用 printf 的格式:
System.out.printf();
具体使用格式与 String.format() 方法一样,请参考上面。
double num = 20.45628;
// 保留两位小数,%n 换行
System.out.printf("%.2f %n", num); // 20.46
int n = 6;
// 右对齐5位
System.out.printf("%5d %n", n);
// 左对齐5位
System.out.printf("%-5d %n", n);
BigDecimal
A BigDecimal由任意精度整数未缩放值和32位整数比例组成。
如果为零或正数,则刻度是小数点右侧的位数。 如果是负数,则数字的非标定值乘以10,以达到等级的否定的幂。
因此, (unscaledValue × 10-scale)代表的BigDecimal值为(unscaledValue × 10-scale) 。
BigDecimal类提供了算术,缩放操作,舍入,比较,散列和格式转换的操作。 toString()方法提供了一个BigDecimal的规范表示。
BigDecimal类使其用户完全控制舍入行为。 如果未指定舍入模式,并且无法表示确切的结果,则抛出异常; 否则,可以通过向操作提供适当的MathContext对象来进行计算,以选择精度和舍入模式。
在这两种情况下,都提供八种舍入方式来控制舍入。 不建议使用此类中的整数字段(如ROUND_HALF_UP )表示舍入模式; 应该使用RoundingMode 枚举的枚举值(如RoundingMode.HALF_UP )。
---- 官方API
BigDecimal 计算和保留小数位是在Java最常用的,也是在财务或者是数据分析中比较重要的方法。
构造方法
Constructor
BigDecimal(char[] in) 将 BigDecimal的字符数组表示 BigDecimal转换为 BigDecimal ,接受与 BigDecimal(String)构造函数相同的字符序列。
BigDecimal(char[] in, int offset, int len) 将 BigDecimal的字符阵列表示 BigDecimal转换为 BigDecimal ,接受与 BigDecimal(String)构造函数相同的字符序列,同时允许指定子数组。
BigDecimal(char[] in, int offset, int len, MathContext mc) 将 BigDecimal的字符数组表示 BigDecimal转换为 BigDecimal ,接受与 BigDecimal(String)构造函数相同的字符序列,同时允许根据上下文设置指定子数组并进行舍入。
BigDecimal(char[] in, MathContext mc) 将 BigDecimal的字符数组表示 BigDecimal转换为 BigDecimal ,接受与 BigDecimal(String)构造函数相同的字符序列,并根据上下文设置进行舍入。
BigDecimal(double val) 将 double转换为 BigDecimal ,它是 double的二进制浮点值的精确十进制表示。
BigDecimal(double val, MathContext mc) 将 double转换为 BigDecimal ,根据上下文设置进行舍入。
BigDecimal(int val) 将 int翻译成 BigDecimal 。
BigDecimal(int val, MathContext mc) 将 int转换为 BigDecimal ,根据上下文设置进行舍入。
BigDecimal(long val) 将 long翻译成 BigDecimal 。
BigDecimal(long val, MathContext mc) 将 long转换为 BigDecimal ,根据上下文设置进行舍入。
BigDecimal(String val) 将 BigDecimal的字符串表示 BigDecimal转换为 BigDecimal 。
BigDecimal(String val, MathContext mc) 将 BigDecimal的字符串表示 BigDecimal转换为 BigDecimal ,接受与 BigDecimal(String)构造函数相同的字符串,根据上下文设置进行舍入。
BigDecimal(BigInteger val) 将 BigInteger翻译成 BigDecimal 。
BigDecimal(BigInteger unscaledVal, int scale) 将 BigInteger值和 int量表翻译成 BigDecimal 。
BigDecimal(BigInteger unscaledVal, int scale, MathContext mc) 将 BigInteger值和 int标度转换为 BigDecimal ,根据上下文设置进行舍入。
BigDecimal(BigInteger val, MathContext mc) 根据上下文设置将 BigInteger转换为 BigDecimal舍入。
舍入方式:
BigDecimal.setScale(int newScale, int roundingMode); // 设置格式化小数位
// 在这个方法中int roundingMode具体的参数如下
BigDecimal.ROUND_UP; //向远离0的方向舍入,进位处理,2.35变为2.4
BigDecimal.ROUND_DOWN; // 向零方向舍入,3.35变为3.3
BigDecimal.ROUND_CEILING; // 向正无穷方向舍入
BigDecimal.ROUND_FLOOR; // 向负无穷方向舍入
BigDecimal.ROUND_HALF_UP; // 向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,向上舍入, 1.55保留一位小数结果为1.6
BigDecimal.ROUND_HALF_DOWN; // 向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,向下舍入, 例如1.55 保留一位小数结果为1.5
BigDecimal.ROUND_HALF_EVEN; // 向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,如果保留位数是奇数,使用ROUND_HALF_UP ,如果是偶数,使用
BigDecimal.ROUND_UNNECESSARY; // 计算结果是精确的,不需要舍入模式
上面的BigDecimal.舍入方式已经过时,改为RoundingMode.舍入方式
如下图:
具体示例
double n = sc.nextDouble(); // 输入一个数
int k = sc.nextInt(); // 保留 k 位小数
double x = 100.0 * n / 7;
BigDecimal bd = new BigDecimal(x); // 获取
bd = bd.setScale(k, RoundingMode.HALF_UP); // 设置保留k位,舍入方式 RoundingMode.HALF_UP:四舍五入
小数点后保留指定n位数
上面谈了这么久,下面引入正题 小数点后保留指定n位数。
printf()
经常使用的 System.out.printf()
,想着能不能指定保留的位数 k。
比如:
保留2位
printf("%.2f")
能不能这样保留 k 位?
printf("%.kf")
System.out.printf("%.(%n)f", k, n);
×
发现不可以
o(╥﹏╥)o
后来发现大佬的C语言题解,有一种方法:
#include <stdio.h>
int main()
{
#ifdef LOCAL
freopen("E:\\input.txt", "r", stdin);
#endif
char s[] = "%.0f%%\\n";
int t, n, k;
scanf("%d", &t);
while (t--)
{
scanf("%d%d", &n, &k);
printf((s[2] = k + '0', s), 100.0 * n / 7);
}
return 0;
}
试着改成Java版:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int t = sc.nextInt();
char[] s = {'%', '.', '0', 'f', '%', '%', '\\n'};
while (t-- > 0) {
int n = sc.nextInt();
int k = sc.nextInt();
s[2] = (char)(k + '0'); // '0' ASCII:48
System.out.printf(new String(s), 100.0 * n / 7);
}
}
}
结果如下:
BigDecimal
参考上面介绍:
BigDecimal.setScale(int newScale, int roundingMode);
double n = sc.nextDouble();
int k = sc.nextInt(); // 保留 k 位
double x = 100.0 * n / 7;
BigDecimal bd = new BigDecimal(x);
bd = bd.setScale(k, RoundingMode.HALF_UP); // 设置 保留位数,及舍入方式:四舍五入
System.out.println(bd);
结果如下:
特别注意
在练习使用过程中,发现一个特殊的地方:
当浮点数位 0 时,保留 k 位小数,输出结果会有变化:
这算一个特殊的地方,比赛时试了几次,一直错误,罚时++
o(╥﹏╥)o
后来我们对 0 的情况特殊考虑,就 AK 了!
题目大意:
计算 n 门 course 成绩,计算平均成绩,并保留指定位数。
代码如下:
int n = sc.nextInt();
int k = sc.nextInt();
double sum = 0;
for (int i = 0; i < n; i++) {
sum += sc.nextInt();
}
if(sum!=0) {
BigDecimal bd = new BigDecimal(sum);
BigDecimal N = new BigDecimal(n);
bd = bd.divide(N, k, RoundingMode.FLOOR); // 除 N,保留 k位,舍入方式:下舍入
System.out.println(bd);
} else {
System.out.print(0+".");
for(int i=0;i<k;i++){
System.out.print(0);
}
System.out.println();
}
}
附:另外还有一种保留 k位小数的方式:模拟手工除法
联想下:手工如何计算 除法
…
当 余数 不足以 整除 除数时,余数乘 10,然后计算循环 k 次,除以 除数。注意:每次保留 商的结果。
代码就不再实现了,o(╥﹏╥)o,两篇博客,整理了几个小时.
感谢博客 Link
感谢 两位队友&宋佬
加油!!!
以上是关于Java 数据格式化&小数点后保留指定位数的主要内容,如果未能解决你的问题,请参考以下文章