【问题标题】:How do I get whole and fractional parts from double in JSP/Java?如何从 JSP/Java 中的 double 中获取整数和小数部分?
【发布时间】:2010-09-25 12:11:26
【问题描述】:

如何在 JSP/Java 中从 double 中获取整数和小数部分?如果值为 3.25 那么我想得到fractional =.25, whole = 3

我们如何在 Java 中做到这一点?

【问题讨论】:

  • 您似乎对尾数和指数的概念不准确。它们不仅仅是“整体”和“部分”。见en.wikipedia.org/wiki/Floating_point
  • 实际上,在“嘿……这不叫指数”之前,我读了大约 5 篇文章。我的大脑扔掉了单词并开始解决问题..阅读编程材料的坏习惯给了我:)
  • 另外,出于其他原因,请重新表述问题 OP..。
  • 听起来有点像家庭作业问题。
  • 哦,我明白了。我已经想知道他是如何得到如此奇怪的结果

标签: java math jsp


【解决方案1】:

最初的问题要求指数和尾数,而不是小数和整数部分。

要从双精度数中获取指数和尾数,您可以将其转换为 IEEE 754 表示并提取如下所示的位:

long bits = Double.doubleToLongBits(3.25);

boolean isNegative = (bits & 0x8000000000000000L) != 0; 
long exponent      = (bits & 0x7ff0000000000000L) >> 52;
long mantissa      =  bits & 0x000fffffffffffffL;

【讨论】:

  • 尾数的第一位是不是隐式设置为1,所以尾数应该是(bits & 0x000fffffffffffffL) | 0x0010000000000000L?
  • Rasmus 它不是一个 ryt 输出输出:指数 0 和尾数 2814749767106560 如果你选择 urs agnul,尾数是 0
  • 获得 4 票赞成:) 虽然我看到代码试图在其关节处拆分双精度值,但代码似乎没有输出正确的值。
  • @agnul:我认为“尾数”通常仅指位的值。您可以通过(有时)添加 1 位将其转换为有效数字。但根据维基百科,尾数这个词现在已被弃用,取而代之的是“分数”。
【解决方案2】:
double value = 3.25;
double fractionalPart = value % 1;
double integralPart = value - fractionalPart;

【讨论】:

  • 为什么这被否决了?工作正常,我的编辑也适用于负值。
  • 整数部分可以是 => long longPart = (long)3.25
  • 对负数无效。价值观。 IE。 -3.25 % 1 = 0.75 而不是 0.25。所以integralPart 将是-3.25 - 0.75 = -4。
  • @WindRider,我检查了负数.. 及其作品.. 但是对于数量较少的小数位,会有轻微的错误。前任。对于 -03.0025 它返回 -0.0024999999999999467 和 -3.0
  • 这里的混淆是因为某些语言,例如 Python,使用% 来表示模数 (-3.25 % 1 == 0.75),而其他语言,例如 Java、Fortran、C 和 C++,使用 %表示余数 (-3.25 % 1 == -0.25)。 WindRider 可能为了方便起见将其输入到 Python REPL 中,但该答案具有误导性,因为此问题与 JVM 有关。
【解决方案3】:

[编辑:问题最初是问如何获得尾数和指数。]

其中 n 是获得真正尾数/指数的数​​字:

exponent = int(log(n))
mantissa = n / 10^exponent

或者,要获得您正在寻找的答案:

exponent = int(n)
mantissa = n - exponent

这些并不完全是 Java,但应该很容易转换。

【讨论】:

    【解决方案4】:

    IEEE 双浮点数的尾数和指数是这样的值

    value = sign * (1 + mantissa) * pow(2, exponent)
    

    如果尾数的形式为 0.101010101_base 2(即其最高有效位被移动到二进制点之后)并且根据偏差调整指数。

    从 1.6 开始,java.lang.Math 还提供了直接获取无偏指数的方法(称为 getExponent(double))

    但是,您要求的数字是数字的整数部分和小数部分,可以使用

    integral = Math.floor(x)
    fractional = x - Math.floor(x)
    

    尽管您可能希望以不同的方式处理负数(floor(-3.5) == -4.0),这取决于您想要这两个部分的原因。

    我强烈建议您不要称这些尾数和指数。

    【讨论】:

      【解决方案5】:

      http://www.java2s.com/Code/Java/Data-Type/Obtainingtheintegerandfractionalparts.htm

      double num;
      long iPart;
      double fPart;
      
      // Get user input
      num = 2.3d;
      iPart = (long) num;
      fPart = num - iPart;
      System.out.println("Integer part = " + iPart);
      System.out.println("Fractional part = " + fPart);
      

      输出:

      Integer part = 2
      Fractional part = 0.2999999999999998
      

      【讨论】:

      • 实际上这个页面是谷歌搜索“从双java中获取部分和全部部分”的第一个命中=)
      • 其实这个答案是不正确的,因为大于 long 的值可以表示它会在小数部分给出巨大的数字。下面的 Dan Vinton 回答同样简单,并且总是返回正确的结果。
      • 实际上,这是不正确的,正如您在输出中看到的那样。输入是 3 的分数,输出是 29999999...虽然使用 BigDecimal 而不是 Double 可以解决问题
      • @Alex 不,输入的数字非常接近2.3,但肯定不是2.3。并且输出没有任何问题,除非您想要超过 10 个有效数字。您只需要在每个输出中进行一些舍入(例如,格式%.9f),这通常比BigDecimal 更轻松。这里唯一的问题是溢出。
      • 将 double 转换为 int 几乎总是一个坏主意。因为例如对于(long)1.0e100,您将得到 0。很多时候,您只需要使用 floor() 的 double 值简单地“下限”。如果您想要整数部分和分数部分,请使用modf()。真的,这是一个糟糕的答案。
      【解决方案6】:
      public class MyMain2 {
          public static void main(String[] args) {
              double myDub;
              myDub=1234.5678;
              long myLong;
              myLong=(int)myDub;
              myDub=(myDub%1)*10000;
              int myInt=(int)myDub;
              System.out.println(myLong + "\n" + myInt);
          }
      }
      

      【讨论】:

      • 这仅在数字恰好有 4 位小数时才有效。不然。
      【解决方案7】:

      由于这个1年前的问题是由更正问题主题的人提出的,并且这个问题被标记为jsp,并且这里没有人能够给出JSP有针对性的答案,here是我针对 JSP 的贡献。

      使用JSTL(只需将jstl-1.2.jar 放入/WEB-INF/libfmt taglib。有一个<fmt:formatNumber> 标记,它完全符合您的要求,并且借助maxFractionDigitsmaxIntegerDigits 属性以一种非常简单的方式完成。

      这是一个SSCCE,只需复制'n'paste'n'运行它。

      <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
      
      <%
          // Just for quick prototyping. Don't do this in real! Use servlet/javabean.
          double d = 3.25;
          request.setAttribute("d", d);
      %>
      
      <!doctype html>
      <html lang="en">
          <head>
              <title>SO question 343584</title>
          </head>
          <body>
              <p>Whole: <fmt:formatNumber value="${d}" maxFractionDigits="0" />
              <p>Fraction: <fmt:formatNumber value="${d}" maxIntegerDigits="0" />
          </body>
      </html>
      

      输出:

      全部:3

      分数:.25

      就是这样。无需借助原始 Java 代码对其进行按摩。

      【讨论】:

        【解决方案8】:

        由于fmt:formatNumber 标记并不总是产生正确的结果,这里是另一种仅限 JSP 的方法:它只是将数字格式化为字符串,并在字符串上进行其余的计算,因为这样更容易并且不会'不涉及进一步的浮点运算。

        <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
        <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
        
        <%
          double[] numbers = { 0.0, 3.25, 3.75, 3.5, 2.5, -1.5, -2.5 };
          pageContext.setAttribute("numbers", numbers);
        %>
        
        <html>
          <body>
            <ul>
              <c:forEach var="n" items="${numbers}">
                <li>${n} = ${fn:substringBefore(n, ".")} + ${n - fn:substringBefore(n, ".")}</li>
              </c:forEach>
            </ul>
          </body>
        </html>
        

        【讨论】:

        • 试试我的例子中的所有数字。 fmt:formatNumber 对其参数进行四舍五入,在这种情况下不需要。
        【解决方案9】:

        你必须首先找到小数点后有多少位的主要逻辑。
        此代码适用于最多 16 位的任何数字。如果您使用 BigDecimal,您最多可以运行 18 位数字。将输入值(你的数字)放到变量“num”中,这里作为一个例子,我已经硬编码了它。

        double num, temp=0;
        double frac,j=1;
        
        num=1034.235;
        // FOR THE FRACTION PART
        do{
        j=j*10;
        temp= num*j;
        }while((temp%10)!=0);       
        
        j=j/10;
        temp=(int)num;
        frac=(num*j)-(temp*j);
        
        System.out.println("Double number= "+num);      
        System.out.println("Whole part= "+(int)num+" fraction part= "+(int)frac);
        

        【讨论】:

        • 老兄,对于一个简单的问题,这是一个极其复杂的答案。你看过接受的答案了吗?
        • 现在投反对票的人(不是我顺便说一句)应该解释为什么投反对票。这不好。但是我们所有人在某个时候都得了 1 分。
        • @Gray 问题是将 3.25 区分为“3”和“25”,并且接受的答案永远不会给出“25”,它总是会给出“2599999999”
        • @Gray 我知道谁投了反对票,这是一个名叫 Eji(老用户)的家伙嘲笑我在这个博客上发布的每一条评论、答案和问题。最后向版主投诉。
        • 如果您希望小数部分为整数,此答案非常有用
        【解决方案10】:

        不知道这是否更快,但我正在使用

        float fp = ip % 1.0f;
        

        【讨论】:

          【解决方案11】:

          其中很多答案都有可怕的舍入错误,因为它们将数字从一种类型转换为另一种类型。怎么样:

          double x=123.456;
          double fractionalPart = x-Math.floor(x);
          double wholePart = Math.floor(x);
          

          【讨论】:

          • @justshams 使用 Math.abs 怎么样?
          【解决方案12】:

          接受的答案不适用于 -0 和 -1.0 之间的负数 也给小数部分负数。

          例如: 对于数字 -0,35

          返回

          整数部分 = 0 小数部分 = -0.35

          如果你正在使用 GPS 坐标,最好将整数部分的符号作为结果:

          整数部分 = -0 小数部分 = 0.35

          这些数字用于例如 GPS 坐标,其中纬度或经度位置的符号很重要

          提议代码:

              double num;
              double iPart;
              double fPart;
          
              // Get user input
              num = -0.35d;
              iPart = (long) num;
              //Correct numbers between -0.0 and -1.0
              iPart = (num<=-0.0000001 && num>-1.0)? -iPart : iPart ;
              fPart = Math.abs(num - iPart);
              System.out.println(String.format("Integer part = %01.0f",iPart));
              System.out.println(String.format("Fractional part = %01.04f",fPart));
          

          输出:

          Integer part = -0
          Fractional part = 0,3500
          

          【讨论】:

            【解决方案13】:

            从 Java 8 开始,您可以使用Math.floorDiv

            它返回小于或等于代数商的最大(最接近正无穷大)int 值。

            一些例子:

            floorDiv(4, 3) == 1
            floorDiv(-4, 3) == -2
            

            或者,可以使用/ 运算符:

            (4 / 3) == 1
            (-4 / 3) == -1
            

            参考资料:

            【讨论】:

              【解决方案14】:

              我会使用 BigDecimal 作为解决方案。像这样:

                  double value = 3.25;
                  BigDecimal wholeValue = BigDecimal.valueOf(value).setScale(0, BigDecimal.ROUND_DOWN);
                  double fractionalValue = value - wholeValue.doubleValue();
              

              【讨论】:

                【解决方案15】:
                String value = "3.06";
                
                if(!value.isEmpty()){
                    if(value.contains(".")){    
                        String block = value.substring(0,value.indexOf("."));
                        System.out.println(block);
                    }else{
                        System.out.println(value);
                    }
                }
                

                【讨论】:

                • 此答案已被标记为低质量。如果它回答了问题,请考虑添加一些文字来解释它是如何工作的。
                【解决方案16】:

                如果您的号码是 2.39999999999999,该怎么办。我想你想得到确切的十进制值。然后使用 BigDecimal:

                Integer x,y,intPart;
                BigDecimal bd,bdInt,bdDec;
                bd = new BigDecimal("2.39999999999999");
                intPart = bd.intValue();
                bdInt = new BigDecimal(intPart);
                bdDec = bd.subtract(bdInt);
                System.out.println("Number : " + bd);
                System.out.println("Whole number part : " + bdInt);
                System.out.println("Decimal number part : " + bdDec);
                

                【讨论】:

                  【解决方案17】:
                  // target float point number
                  double d = 3.025;
                  
                  // transfer the number to string
                  DecimalFormat df = new DecimalFormat();
                  df.setDecimalSeparatorAlwaysShown(false);
                  String format = df.format(d);
                  
                  // split the number into two fragments
                  int dotIndex = format.indexOf(".");
                  int iPart = Integer.parseInt(format.substring(0, dotIndex)); // output: 3
                  double fPart = Double.parseDouble(format.substring(dotIndex)); // output: 0.025
                  

                  【讨论】:

                    【解决方案18】:

                    好吧,这可能有点晚了,但我认为最好和更准确的方法是使用 BigDecimal

                    double d = 11.38;
                    
                    BigDecimal bigD = BigDecimal.valueOf(d);
                    int intPart = bigD.intValue();
                    double fractionalPart = bigD.subtract(BigDecimal.valueOf(intPart)).doubleValue();
                    
                    System.out.println(intPart); // 11
                    System.out.println(fractionalPart ); //0.38
                    

                    【讨论】:

                    • 如果你有一个双精度,它有浮点不精确。将其转换为 BigDecimal 不会神奇地恢复其精度。
                    • @Taschi 我认为问题在于将 int 和小数部分分开,而不是恢复其精度!
                    • 奥马尔,你特别谈到你的方法“更准确”,我认为这不是真的。你的回答是完全可以接受的,但这个措辞对我来说似乎有误导性,这就是我评论它的原因。
                    • @Taschi,我说因为在许多答案中,当你得到输出时你会失去价值,例如input (5.03) output int = 5 , fractional = 0.0299999 ,我们谈论的是投入和产出,你投入价值并在不损失 0.001% 的情况下取回你的价值!而且这个准确,不会误导!
                    • 是的。当您首先将某些内容存储为双精度时,您会失去精度。转换为 BigDecimal 时的舍入也会丢失精度。这两种精度损失可能会相互抵消,但这并不能“恢复”精度,因为恢复精度在数学上是不可能的。你不能凭空提取信息。
                    猜你喜欢
                    • 2012-10-13
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2014-11-04
                    • 1970-01-01
                    • 2015-01-13
                    相关资源
                    最近更新 更多