int i =132;
byte b =(byte)i; System.out.println(b);
mindboggling ทำไมเอาท์พุท-124?
int i =132;
byte b =(byte)i; System.out.println(b);
mindboggling ทำไมเอาท์พุท-124?
คำตอบ:
ใน Java intคือ 32 บิต byteคือ bits8
ชนิดดั้งเดิมมากที่สุดใน Java มีการเซ็นชื่อและbyte, short, intและlongมีการเข้ารหัสในการเติมเต็มสอง ( charประเภทนี้ไม่ได้ลงนามและแนวคิดของเครื่องหมายไม่สามารถใช้ได้กับboolean)
ในรูปแบบตัวเลขนี้บิตที่สำคัญที่สุดระบุเครื่องหมายของตัวเลข หากต้องการบิตมากขึ้นบิตที่สำคัญที่สุด ("MSB") จะถูกคัดลอกไปยัง MSB ใหม่
ดังนั้นถ้าคุณมีไบต์255: 11111111
และคุณต้องการแทนค่าเป็นint(32 บิต) คุณเพียงแค่คัดลอก 1 ไปทางซ้าย 24 ครั้ง
วิธีหนึ่งในการอ่านจำนวนบวกของสองลบคือเริ่มต้นด้วยบิตที่มีนัยสำคัญน้อยที่สุดเลื่อนไปทางซ้ายจนกว่าคุณจะพบ 1 แรกจากนั้นกลับด้านทุกบิตในภายหลัง ตัวเลขผลลัพธ์คือจำนวนบวกของตัวเลขนั้น
ตัวอย่างเช่น11111111ไป=00000001 -1นี่คือสิ่งที่ Java จะแสดงเป็นค่า
สิ่งที่คุณอาจต้องการทำคือรู้ค่าที่ไม่ได้ลงชื่อของไบต์
คุณสามารถทำได้ด้วย bitmask ที่ลบทุกอย่างยกเว้น 8 บิตที่มีนัยสำคัญน้อยที่สุด (0xff)
ดังนั้น:
byte signedByte = -1;
int unsignedByte = signedByte & (0xff);
System.out.println("Signed: " + signedByte + " Unsigned: " + unsignedByte);
จะพิมพ์ออกมา: "Signed: -1 Unsigned: 255"
เกิดอะไรขึ้นที่นี่?
เรากำลังใช้ bitwise AND เพื่อปกปิดบิตเครื่องหมายภายนอกทั้งหมด (ค่า 1 อยู่ทางซ้ายของ 8 บิตที่มีนัยสำคัญน้อยที่สุด) เมื่อ int ถูกแปลงเป็นไบต์ Java จะตัดส่วนที่เหลือ 24 บิตออกไป
1111111111111111111111111010101
&
0000000000000000000000001111111
=
0000000000000000000000001010101
เนื่องจากบิตที่ 32 เป็นบิตเครื่องหมายแทนบิตที่ 8 (และเราตั้งค่าบิตเครื่องหมายเป็น 0 ซึ่งเป็นค่าบวก) 8 บิตดั้งเดิมจากไบต์จะถูกอ่านโดย Java เป็นค่าบวก
signedByte & (0xff)เกิดขึ้นในที่0xffนี้คือมันเป็นตัวอักษร interger ดังนั้น signedByte จึงได้รับการเลื่อนขั้นเป็นจำนวนเต็มก่อนที่จะดำเนินการบิตไวซ์
132ในตัวเลข ( ฐาน 10 ) เป็น1000_0100บิต ( ฐาน 2 ) และ Java เก็บintใน 32 บิต:
0000_0000_0000_0000_0000_0000_1000_0100
อัลกอริทึมสำหรับ int-to-byte ถูกตัดด้านซ้าย อัลกอริทึม for System.out.printlnis two's -complement (Two's-complement is if leftmost bit is 1, ตีความเป็น negative -complement (invert bits) minus-one); ดังนั้นSystem.out.println(int-to-byte( ))คือ:
0000_0000_0000_0000_0000_0000_1000_0100) [)))])1000_0100[)))])1000_0100))))1000_0011)))0111_1100))intไปbyteเป็นแปลงสูญเสีย (เช่นข้อมูลสูญหาย) ดังนั้นจึงไม่มีทางที่จะแปลงกลับเป็นintค่าเดิมได้
132 อยู่นอกช่วงของไบต์ซึ่งเป็น -128 ถึง 127 (Byte.MIN_VALUE ถึง Byte.MAX_VALUE) แทนค่าบิตบนสุดของค่า 8 บิตจะถือว่าเป็นเครื่องหมายซึ่งระบุว่าเป็นค่าลบในกรณีนี้ ดังนั้นจำนวนคือ 132 - 256 = -124
นี่เป็นวิธีเชิงกลที่ไม่มีทฤษฎีที่ทำให้ไขว้เขว:
วิธีการที่เป็นประโยชน์มากขึ้นนี้เป็นไปตามคำตอบทางทฤษฎีข้างต้น ดังนั้นผู้ที่ยังอ่านหนังสือ Java ที่บอกว่าจะใช้โมดูโล่นี่เป็นสิ่งที่ผิดอย่างแน่นอนเนื่องจาก 4 ขั้นตอนที่ฉันระบุไว้ข้างต้นไม่ใช่การทำงานของโมดูโลอย่างแน่นอน
http://iiti.ac.in/people/~tanimad/JavaTheCompleteReference.pdfหน้า 59
ใน Java byte(N = 8) และint(N = 32) จะแสดงโดย 2s-complement ที่แสดงด้านบน
จากสมการที่7เป็นลบสำหรับแต่ในเชิงบวกสำหรับbyteint
coef: a7 a6 a5 a4 a3 a2 a1 a0
Binary: 1 0 0 0 0 1 0 0
----------------------------------------------
int: 128 + 0 + 0 + 0 + 0 + 4 + 0 + 0 = 132
byte: -128 + 0 + 0 + 0 + 0 + 4 + 0 + 0 = -124
บ่อยครั้งในหนังสือคุณจะพบคำอธิบายของการแคสต์จาก int เป็นไบต์ว่าดำเนินการโดยการหารโมดูลัส สิ่งนี้ไม่ถูกต้องอย่างเคร่งครัดดังที่แสดงด้านล่างสิ่งที่เกิดขึ้นจริงคือ 24 บิตที่สำคัญที่สุดจากค่าไบนารีของจำนวน int จะถูกละทิ้งทำให้เกิดความสับสนหากตั้งค่าบิตซ้ายสุดที่เหลือซึ่งกำหนดจำนวนเป็นค่าลบ
public class castingsample{
public static void main(String args[]){
int i;
byte y;
i = 1024;
for(i = 1024; i > 0; i-- ){
y = (byte)i;
System.out.print(i + " mod 128 = " + i%128 + " also ");
System.out.println(i + " cast to byte " + " = " + y);
}
}
}
อัลกอริทึมด่วนที่จำลองวิธีการทำงานมีดังต่อไปนี้:
public int toByte(int number) {
int tmp = number & 0xff
return (tmp & 0x80) == 0 ? tmp : tmp - 256;
}
วิธีนี้ทำงานอย่างไร มองหาคำตอบdaixtr การใช้อัลกอริทึมที่แน่นอนซึ่งระบุไว้ในคำตอบของเขามีดังต่อไปนี้:
public static int toByte(int number) {
int tmp = number & 0xff;
if ((tmp & 0x80) == 0x80) {
int bit = 1;
int mask = 0;
for(;;) {
mask |= bit;
if ((tmp & bit) == 0) {
bit <<=1;
continue;
}
int left = tmp & (~mask);
int right = tmp & mask;
left = ~left;
left &= (~mask);
tmp = left | right;
tmp = -(tmp & 0xff);
break;
}
}
return tmp;
}
หากคุณต้องการทำความเข้าใจในทางคณิตศาสตร์เช่นวิธีการทำงานนี้
ดังนั้นโดยทั่วไปแล้วตัวเลข b / w -128 ถึง 127 จะเขียนเช่นเดียวกับค่าทศนิยมเหนือกว่า (ตัวเลขของคุณ - 256)
เช่น. 132 คำตอบจะเป็น 132 - 256 = - 124 เช่น
256 + คำตอบของคุณในจำนวน 256 + (-124) คือ 132
ตัวอย่างอื่น
double a = 295.04;
int b = 300;
byte c = (byte) a;
byte d = (byte) b; System.out.println(c + " " + d);
เอาต์พุตจะเป็น 39 44
(295 - 256) (300 - 256)
หมายเหตุ: จะไม่พิจารณาตัวเลขหลังจุดทศนิยม
ตามแนวคิดแล้วการลบซ้ำ ๆ ของ 256 จะทำกับตัวเลขของคุณจนกว่าจะอยู่ในช่วง -128 ถึง +127 ในกรณีของคุณคุณเริ่มต้นด้วย 132 แล้วลงท้ายด้วย -124 ในขั้นตอนเดียว
ในทางคำนวณสิ่งนี้สอดคล้องกับการแยก 8 บิตที่มีนัยสำคัญน้อยที่สุดจากจำนวนเดิมของคุณ (และโปรดทราบว่าบิตที่สำคัญที่สุดของ 8 เหล่านี้กลายเป็นบิตเครื่องหมาย)
โปรดทราบว่าในภาษาอื่นไม่ได้กำหนดลักษณะการทำงานนี้ (เช่น C และ C ++)
N is input number
case 1: 0<=N<=127 answer=N;
case 2: 128<=N<=256 answer=N-256
case 3: N>256
temp1=N/256;
temp2=N-temp*256;
if temp2<=127 then answer=temp2;
else if temp2>=128 then answer=temp2-256;
case 4: negative number input
do same procedure.just change the sign of the solution