/*
* Copyright 2010 Georgios Migdos <cyberpython@gmail.com>.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* under the License.
*/
package util.binary.bitpattern;
/**
*
* @author Georgios Migdos <cyberpython@gmail.com>
*/
public class BitPatternUtils {
public static String hexToBinaryString(String hexValue, int minLength) {
if (hexValue.matches("0x[0-9a-fA-F]+")) {
StringBuilder sb = new StringBuilder(Integer.toBinaryString(Integer.parseInt(hexValue.substring(2), 16)));
while (sb.length() < minLength) {
sb.insert(0, '0');
}
return sb.toString();
} else {
throw new NumberFormatException("Invalid hex value: " + hexValue);
}
}
public static String binaryToHexString(String binaryValue) {
return "0x"+Integer.toHexString(Integer.parseInt(binaryValue,2)).toUpperCase();
}
public static String binaryToHexString(String binaryValue, int minLength) {
StringBuilder sb = new StringBuilder(Integer.toHexString(Integer.parseInt(binaryValue,2)).toUpperCase());
while (sb.length() < minLength) {
sb.insert(0, '0');
}
return "0x"+sb.toString();
}
public static String toBinaryString(int value, int minLength) {
StringBuilder sb = new StringBuilder(Integer.toBinaryString(value));
while (sb.length() < minLength) {
sb.insert(0, '0');
}
return sb.toString();
}
public static String toHexString(int value, int minLength) {
StringBuilder sb = new StringBuilder(Integer.toHexString(value).toUpperCase());
while (sb.length() < minLength) {
sb.insert(0, '0');
}
return sb.toString();
}
private static int getExcessThreeValue(String bits) {
return Integer.parseInt(bits, 2) - 4;
}
private static String toExcessThreeValue(int value) {
return BitPatternUtils.toBinaryString(value + 4, 3);
}
public static IBitPattern addFloats(IBitPattern a, IBitPattern b) throws BitPatternOverflowException {
float fA = byteToFloatValue(a);
float fB = byteToFloatValue(b);
float f = fA + fB;
if( (f < -7.5f) || (f > 7.5f) ){
throw new BitPatternOverflowException("Overflow caused by value: "+f);
}else{
return floatToBytePattern(f);
}
}
public static IBitPattern floatToBytePattern(float f) {
return new BitPattern(8, getByteBinaryStringForFloat(f));
}
public static float byteToFloatValue(IBitPattern bytePattern) {
return getFloatValueForByteBinaryString(bytePattern.toBinaryString());
}
private static String getByteBinaryStringForFloat(float f) {
String signBit = "0";
if (f < 0) {
signBit = "1";
f = -f;
}
int integerPart = (int) f;
float fractionalPart = f - integerPart;
fractionalPart *= 16;
float tmp = fractionalPart;
int factor = 16;
int count = 0;
while ((tmp - (int) tmp > 0) && (count < 4)) {
factor = factor * 2;
tmp = (f - integerPart) * factor;
count++;
}
String fractionalBits = Integer.toBinaryString((int) tmp);
count = count + 4 - fractionalBits.length();
while (count > 4) {
fractionalBits = "0" + fractionalBits;
count--;
}
int moveLeft = -count;
String integerBits = integerPart == 0 ? "" : Integer.toBinaryString(integerPart);
String exp = integerBits.length() == 0 ? toExcessThreeValue(moveLeft) : toExcessThreeValue(integerBits.length());
String result = signBit + exp + integerBits + fractionalBits;
while (result.length() < 8) {
result = result + "0";
}
return result.substring(0, 8);
}
private static float getFloatValueForByteBinaryString(String bits) {
if (bits.matches("[01]{8}")) {
int sign = 1;
if (bits.charAt(0) == '1') {
sign = -1;
}
float result = 0f;
int exponent = getExcessThreeValue(bits.substring(1, 4));
StringBuilder mantissaBitsBuilder = new StringBuilder(bits.substring(4));
if (exponent >= 0) {
if (exponent > 4) {
for (int i = 4; i < exponent; i++) {
mantissaBitsBuilder.append('0');
}
}
} else {
for (int i = 0; i > exponent; i--) {
mantissaBitsBuilder.insert(0, '0');
}
}
String mantissaBits = mantissaBitsBuilder.toString();
int integerPart = 0;
if (exponent > 0) {
integerPart = Integer.parseInt(mantissaBits.substring(0, exponent), 2);
mantissaBits = mantissaBits.substring(exponent);
}
float fractionalPart = Integer.parseInt(mantissaBits, 2) / (float) (Math.pow(2, mantissaBits.length()));
result = integerPart + fractionalPart;
return sign * result;
} else {
throw new NumberFormatException("Invalid binary representation of a byte containing a float value: " + bits);
}
}
public static void main(String[] args) {
/*try{
System.out.println(getFloatValueForByteBinaryString("01101011"));//2.75
//01101011
System.out.println(getFloatValueForByteBinaryString("00111100"));//0.375
//00111100
System.out.println(getFloatValueForByteBinaryString("01001100"));//0.75
//01001100
System.out.println(getFloatValueForByteBinaryString("11101011"));//-2.75
//11101011
System.out.println(getFloatValueForByteBinaryString("00001000"));//0.03125
//00001000
System.out.println(getFloatValueForByteBinaryString("00000010"));//0.0078125
//00000010
System.out.println(getFloatValueForByteBinaryString("00000001"));//0.00390625
//00000001
System.out.println(getFloatValueForByteBinaryString("10101101"));//-0.203125
//10101101
System.out.println(getFloatValueForByteBinaryString("01101010"));//2.5
System.out.println(getByteBinaryStringForFloat(2.75f));
System.out.println(getByteBinaryStringForFloat(0.375f));
System.out.println(getByteBinaryStringForFloat(0.75f));
System.out.println(getByteBinaryStringForFloat(-2.75f));
System.out.println(getByteBinaryStringForFloat(0.03125f));
System.out.println(getByteBinaryStringForFloat(0.0078125f));
System.out.println(getByteBinaryStringForFloat(0.00390625f));
System.out.println(getByteBinaryStringForFloat(-0.203125f));
System.out.println(getByteBinaryStringForFloat(2.0625f)); // truncation error: will return the value for 2.5
System.out.println("2.5 + 2 = "+byteToFloatValue(addFloats(new BitPattern(8, "01101010"), new BitPattern(8, "01101000"))));
}catch(BitPatternOverflowException boe){
System.err.println(boe.getMessage());
}*/
System.out.println(getFloatValueForByteBinaryString("11111111"));
}
}