java中是否有截断双精度的函数?
是否有Java库函数可用于将数字截断为任意小数位数? 比如说java中是否有截断双精度的函数?,java,Java,是否有Java库函数可用于将数字截断为任意小数位数? 比如说 SomeLibrary.truncate(1.575, 2) = 1.57 感谢大多数数字,除非使用精度有保证的十进制类,否则无法获得xxx.yyyy的精确表示形式,例如。要100%可靠地传递参数,必须将参数作为字符串而不是浮点数传递。当以字符串形式给出时,代码很容易编写。原因是, double x = 1.1; 并不意味着x实际上将计算为1.1,仅计算为最接近的可精确表示的数字。请尝试类似的设置比例: 创建了一个方法来执行此操作
SomeLibrary.truncate(1.575, 2) = 1.57
感谢大多数数字,除非使用精度有保证的十进制类,否则无法获得xxx.yyyy的精确表示形式,例如。要100%可靠地传递参数,必须将参数作为字符串而不是浮点数传递。当以字符串形式给出时,代码很容易编写。原因是,
double x = 1.1;
并不意味着x实际上将计算为1.1,仅计算为最接近的可精确表示的数字。请尝试类似的设置比例:
创建了一个方法来执行此操作
public double roundDouble(double d, int places) {
return Math.round(d * Math.pow(10, (double) places)) / Math.pow(10, (double)places);
}
在公共数学中有一个。退房: 它使用BigDecimal实现,并重载以允许指定舍入方法,因此您可以使用它来截断,如下所示:
org.apache.commons.math.util.MathUtils.round(1.575, 2,
java.math.BigDecimal.ROUND_DOWN);
更新:
在上一个版本(Math3)中,此方法位于类中。
org.apache.commons.math3.util.Precision.round(双x,int scale,int roundingMethod)
实际上,这种东西很容易写:
public static double truncate(double value, int places) {
double multiplier = Math.pow(10, places);
return Math.floor(multiplier * value) / multiplier;
}
请注意,它是Math.floor,因为Math.round不会被截断
哦,这返回一个double,因为这是Math类中大多数函数返回的值(比如Math.pow和Math.floor)
注意:双打的准确性很差。首先应该考虑一个BigDecimal解决方案。令人难以置信的是,现在还没有人提出这个问题,Java API早就有了这个确切的目的。下面是一个比使用BigDecimal或Math.pow快很多倍的简短实现
private static long TENS[] = new long[19];
static {
TENS[0] = 1;
for (int i = 1; i < TENS.length; i++) TENS[i] = 10 * TENS[i - 1];
}
public static double round(double v, int precision) {
assert precision >= 0 && precision < TENS.length;
double unscaled = v * TENS[precision];
if(unscaled < Long.MIN_VALUE || unscaled > Long.MAX_VALUE)
return v;
long unscaledLong = (long) (unscaled + (v < 0 ? -0.5 : 0.5));
return (double) unscaledLong / TENS[precision];
}
private static long TENS[]=new long[19];
静止的{
十[0]=1;
对于(inti=1;i=0&&precisionLong.MAX_值)
返回v;
长未标度长=(长)(未标度+(v<0-0.5:0.5));
返回(双精度)无标度长/十位数[精度];
}
删除要品尝的断言。;) 使用这个简单的函数
double truncateDouble(double number, int numDigits) {
double result = number;
String arg = "" + number;
int idx = arg.indexOf('.');
if (idx!=-1) {
if (arg.length() > idx+numDigits) {
arg = arg.substring(0,idx+numDigits+1);
result = Double.parseDouble(arg);
}
}
return result ;
}
我只想补充一下ubuntudroid的解决方案。 我试过了,但它不能取整,所以我不得不补充
df.setRoundingMode(RoundingMode.FLOOR);
只需删除小数部分即可
公共双中继(双值){
返回值-值%1;
}
2注释:BigDecimal
已经有一个构造函数使用了一个Double
。OP似乎也不想把它四舍五入,只是为了截断它。实际上,BalusC是对的,我想截断这个值,你的回答给了我正确的方向,所以我接受了。你需要将舍入模式设置为BigDecimal。向下舍入,而不是向上舍入一半,以真正截断一个值。改进的版本使用正数和负数,而不是舍入。更基本的是,double没有小数位数,因为它们存储为二进制分数。或者使用BigDecimal,这是BigDecimal存在的原因之一。您仍然需要从字符串初始化它,而不是从double初始化。注意:pow是一个非常昂贵的函数。如果性能不是问题,请使用它。我喜欢这种简单明了的解决方案。@Mani(好吧,也适用于EJP所说的):我会注意到警告是有原因的。@Powerlord的目标是将双精度截断为任意小数位数,任何解决方案都应该做到这一点。这段代码没有也不能这样做,不是因为“精确性”,而是因为二进制分数和十进制分数是不可通约的。我看到的唯一问题是,您将参数v
乘以(可能)10的几次幂,这可能会导致溢出。当然,double max值约为10^308,因此大多数人不会注意到这一点,但这是可能的,这是一种令人惊讶的行为(在提交有效值时,您不希望舍入函数出现溢出)。只要注意到未标度值超过long
type,该方法就会失败,这要快得多。如果要求足够的精度,即使参数v
很小,这也可能非常快。@UMad Ok,更改了应处理这两种情况的检查。round(9.625,2)返回9.63,根据问题,这是错误的。答案应该是9。62@PeterLawrey在第(9.62,2)轮到第9.61轮中,下降+0.5将不起作用。问题是double没有实际的小数点,您必须使用BigDecimal,或者应该添加额外的条件。对于给定的示例,代码如下所示:final DecimalFormat df=new DecimalFormat();df.setMaximumFractionDigits(2);df.格式(1.575);最后一个表达式返回一个字符串,该字符串必须转换回double。这将进行舍入,我认为问题是截断而不是舍入。的可能重复项
double truncateDouble(double number, int numDigits) {
double result = number;
String arg = "" + number;
int idx = arg.indexOf('.');
if (idx!=-1) {
if (arg.length() > idx+numDigits) {
arg = arg.substring(0,idx+numDigits+1);
result = Double.parseDouble(arg);
}
}
return result ;
}
df.setRoundingMode(RoundingMode.FLOOR);