-6 | 5 | |
原碼 | 10000110 | 00000101 |
反碼 | 11111001 | 01111010 |
補碼 | 11111010 | 00000101 |
補碼運輸的例子:
-6+5 -4+5
11111010 11111100
+ 00000101 + 00000101
= 11111111 = 00000001
int a=-6; for(int i=0;i<32;i++){ int t=(a & (0x80000000)>>>i)>>>(31-i); System.out.print(t); }
IEEE754 | 符號位 | 指數位 | 尾數位 | 指數偏移量 | 計算公式 | 附加位 |
float(單精度浮點數) | 1[31] | 8[23-30] | 23[0-22] | 127 | s*m*2^(e-127) | e全0 尾數附加位為0 否則為1, 附加位對應2^0 |
double(雙進度浮點數) | 1[63] | 11[52-62] | 52[0-51] | 1023 | s*m*2^(e-1023) | e全0 尾數附加位為0 否則為1, 附加位對應2^0 |
-5的IEEE 754表示.
11000000101000000000000000000000
-1*2^(129-127)*(2^0+2^-2) 紅色的部分對應附加位
一個IEEE754在線小工具: http://www.h-schmidt.net/FloatConverter/IEEE754.html
打印float的IEEE754表示的二進制串
public class FloatString { public static void main(String[] args){ float f = 100.2f; int intString = Float.floatToIntBits(f); if(intString!=0x7f800000||intString!=0xff800000||intString!=0x7fc00000) { for(int i =0;i<32;i++) { int t =( intString & (0x80000000>>>i) ) >>> (31-i); System.out.print(t); } } } }
Java 的進制間轉換.
十進制轉成十六進制:Integer.toHexString(int i)
十進制轉成八進制:Integer.toOctalString(int i)
十進制轉成二進制:Integer.toBinaryString(int i)
十進制轉成別的進制的通用方法:Integer.toString(1, 8);
十六進制轉成十進制:Integer.valueOf("FFFF",16).toString()
八進制轉成十進制:Integer.valueOf("876",8).toString()
二進制轉十進制:Integer.valueOf("0101",2).toString()
轉成十進制的通用方法 Integer.parseInt(s, radix) /Integer.valueOf(s, radix)
Float 到double的轉換錯誤例子:
問題1:double類型轉float類型沒有出錯,float轉double類型出錯。
float f = 121.1f;
double d = f;
System.out.println(d);
輸出:
121.0999984741211
解決辦法1:
float f = 121.1f;
double d ;
BigDecimal bd = new BigDecimal(String.valueOf(f));
d = bd.doubleValue();
System.out.println(d);
輸出:
121.1
問題2:
double d = (3.3-2.1)/0.1;
System.out.println(d);
輸出:
11.999999999999996
解決辦法2:
BigDecimal b = new BigDecimal("3.3").subtract(new BigDecimal("2.1")).divide(new BigDecimal("0.1"));
System.out.println(b.doubleValue());
小數運算時,或可能會產生小數的運算時,都轉換成BigDecimal后再進行,得到結果后再轉換成相應類型。
如果感覺麻煩,可以寫一個基本運算的工具類,參考博客
說明:
java中整數默認是int,小數默認是double類型。(如要得到float類型,則加f如:12.1f)
int:4字節,long:8字節,float:4字節,double:8字節
float類型的變量只有7位的精度,而double類型的變量有15位的精度。
java在運算時會自動的提升變量的精度來進行運算。(double比float精度更高,所以可以自動的從float轉化至double再進行運算。)
BigDecimal介紹:
float和double只能用來做科學計算或者是工程計算,在商業計算中我們要用java.math.BigDecimal.
BigDecimal(double val) Translates a double into a BigDecimal.這個方法會丟失精度.下面是該API中的說明.
Note: the results of this constructor can be somewhat unpredictable. One might assume that new BigDecimal(.1) is exactly equal to .1, but it is actually equal to .1000000000000000055511151231257827021181583404541015625. This is so because .1 cannot be represented exactly as a double (or, for that matter, as a binary fraction of any finite length). Thus, the long value that is being passed in to the constructor is not exactly equal to .1, appearances nonwithstanding.
The (String) constructor, on the other hand, is perfectly predictable: new BigDecimal(".1") is exactly equal to .1, as one would expect. Therefore, it is generally recommended that the (String) constructor be used in preference to this one.
BigDecimal(String val) Translates the String repre sentation of a BigDecimal into a BigDecimal. 這個方法不會丟失精度.
做浮點數運算的工具類
import java.math.BigDecimal; /** * 由於Java的簡單類型不能夠精確的對浮點數進行運算,這個工具類提供精 * 確的浮點數運算,包括加減乘除和四舍五入。 */ public class Arith{ //默認除法運算精度 private static final int DEF_DIV_SCALE = 10; //這個類不能實例化 private Arith(){ } /** * 提供精確的加法運算。 * @param v1 被加數 * @param v2 加數 * @return 兩個參數的和 */ public static double add(double v1,double v2){ BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.add(b2).doubleValue(); } /** * 提供精確的減法運算。 * @param v1 被減數 * @param v2 減數 * @return 兩個參數的差 */ public static double sub(double v1,double v2){ BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.suBTract(b2).doubleValue(); } /** * 提供精確的乘法運算。 * @param v1 被乘數 * @param v2 乘數 * @return 兩個參數的積 */ public static double mul(double v1,double v2){ BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.multiply(b2).doubleValue(); } /** * 提供(相對)精確的除法運算,當發生除不盡的情況時,精確到 * 小數點以后10位,以后的數字四舍五入。 * @param v1 被除數 * @param v2 除數 * @return 兩個參數的商 */ public static double div(double v1,double v2){ return div(v1,v2,DEF_DIV_SCALE); } /** * 提供(相對)精確的除法運算。當發生除不盡的情況時,由scale參數指 * 定精度,以后的數字四舍五入。 * @param v1 被除數 * @param v2 除數 * @param scale 表示表示需要精確到小數點以后幾位。 * @return 兩個參數的商 */ public static double div(double v1,double v2,int scale){ if(scale<0){ throw new IllegalArgumentException( "The scale must be a positive integer or zero"); } BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue(); } /** * 提供精確的小數位四舍五入處理。 * @param v 需要四舍五入的數字 * @param scale 小數點后保留幾位 * @return 四舍五入后的結果 */ public static double round(double v,int scale){ if(scale<0){ throw new IllegalArgumentException( "The scale must be a positive integer or zero"); } BigDecimal b = new BigDecimal(Double.toString(v)); BigDecimal one = new BigDecimal("1"); return b.divide(one,scale,BigDecimal.ROUND_HALF_UP).doubleValue(); } };
參考:http://blog.chinaunix.net/uid-26434689-id-3554399.html