I want to convert a string representing the mantissa portion of a IEEE754 double.
Cannot find if there is such a conversion method in Java, in order to avoid manually adding 1 + 1/2 + 1/4 + 1/8 etc.
|0100000011001010000111110000000000000000000000000000000000000000 --> 13374 in IEEE754
|------------1010000111110000000000000000000000000000000000000000 --> mantissa part
| 1.1010000111110000000000000000000000000000000000000000 --> restoring fixed value 1
String s = "1.1010000111110000000000000000000000000000000000000000"
double mant10 = Double.readFromFloatBinary(s); // does such method exists in Java?
Yes, there are ways to read from a binary representation. But you don't have a representation in an IEEE format.
I would ignore the period and read as a BigInteger base2, then create a value to divide by also using BigInteger:
private static double binaryStringToDouble(String s) {
return stringToDouble(s, 2);
}
private static double stringToDouble(String s, int base) {
String withoutPeriod = s.replace(".", "");
double value = new BigInteger(withoutPeriod, base).doubleValue();
String binaryDivisor = "1" + s.split("\\.")[1].replace("1", "0");
double divisor = new BigInteger(binaryDivisor, base).doubleValue();
return value / divisor;
}
#Test
public void test_one_point_5() {
String s = "1.1";
double d = binaryStringToDouble(s);
assertEquals(1.5, d, 0.0001);
}
#Test
public void test_6_8125() {
String s = "110.1101";
double d = binaryStringToDouble(s);
assertEquals(6.8125, d, 0.0001);
}
#Test
public void test_yours() {
String s = "1.1010000111110000000000000000000000000000000000000000";
double d = binaryStringToDouble(s);
assertEquals(1.632568359375, d, 0.000000000000000001);
}
#Test
public void test_yours_no_trailing_zeros() {
String s = "1.101000011111";
double d = binaryStringToDouble(s);
assertEquals(1.632568359375, d, 0.000000000000000001);
}
Related
I have two BigInteger variables "e" and "n" and i want to concatenate them together as "en".. how do i do this?
Do i need to convert to a string first then back to BigInteger?
My code sets the variables from another class.
public class Key {
public BigInteger getN() {
return n;
}
public void setN(BigInteger n) {
this.n = n;
}
public BigInteger getE() {
return e;
}
public void setE(BigInteger e) {
this.e = e;
}
public BigInteger getD() {
return d;
}
public void setD(BigInteger d) {
this.d = d;
}
public BigInteger e;
public BigInteger n;
public BigInteger d;
public BigInteger publickeyconcat() {
BigInteger myval = (e + n);
return myval;
}
public BigInteger privatekeyconcat(){
BigInteger myval2 = e;
return myval2;
}
}
UPDATE
Have tried the method given in the comments but when converting to use e and n rather than number1 and number2 it doesn't concat them together.
public BigInteger publickeyconcat() {
BigInteger ten=new BigInteger("10");
BigInteger myval=(e.multiply(ten.pow((int)(Math.floor(Math.log10(e.doubleValue()) + 1)))).add(n));
return myval;
}
Because of the effort shown, the power of 10 for multiplying the first number can be gotten as follows:
public static BigInteger concat(BigInteger x, BigInteger y)
{
int ndigits = y.bitLength() * 3 / 10; // Guessed number of digits using 2^10 ≈ 10^3.
BigInteger pow10 = BigInteger.TEN.pow(ndigits);
while (pow10.compareTo(y) > 0) {
pow10 = pow10.divide(BigInteger.TEN);
}
while (pow10.compareTo(y) <= 0) {
pow10 = pow10.multiply(BigInteger.TEN);
}
// Cheating: int ndigits = y.toString().length();
return x.multiply(pow10).add(y);
}
Since other answers have already focused on String Concatenation, let me give you another answer not involving String Concatenation. You can take the number of digits of first number, multiply first number with 10^(no of digits) and add the second number. A crude example would be as follows,
BigInteger ten=new BigInteger("10");
BigInteger number=new BigInteger("1234");
BigInteger number2=new BigInteger("5678");
BigInteger newBigInt=(number.multiply(ten.pow((int)(Math.floor(Math.log10(number.doubleValue()) + 1)))).add(number2));
System.out.println(newBigInt); //would print 12345678
If you just want to concatenate two BigInteger variables, you can do it this way:
public BigInteger publickeyconcat(BigInteger e, BigInteger n) {
String a = String.valueOf(e);
String b = String.valueOf(n);
String val = a + b;
BigInteger myval = new BigInteger(val);
return myval;
}
But if you want to do operations with the numbers, you can do that directly. There is no need for a conversion.
i did this in the end by converting to a string and using string buffer due to the size of BigInteger. I then left as String as i wanted to write it to a file but i could have reverted to BigInteger using the content variable.
public String publickeyconcat() {
String str = String.valueOf(e);
StringBuffer tmp = new StringBuffer(str);
tmp.append(n);
str = tmp.toString();
BigInteger content = new BigInteger(str);
return str;
}
I need to show some times value on a linear chart and I built a snippet code to convert the values from time to float in Java.
My code doesn't works very well because I can't convert from float to time...
This is my result:
From time to float:
7:43 --> 7.7166667
From float to time:
7.7166667 --> 7:60 (this is wrong...I would to see 7:43)
This is my snippet code:
public class Test {
public static void main(String[] args)
{
String time = "7:43";
float timeFloat = Float.parseFloat(time.replace(":","."));
float resultTo100 = convertTo100(timeFloat);
System.out.println(resultTo100);
String resultTo60 = convertTo60(resultTo100);
System.out.println(resultTo60);
}
public static float convertTo100(float input)
{
String input_string = Float.toString(input);
BigDecimal inputBD = new BigDecimal(input_string);
String hhStr = input_string.split("\\.")[0];
BigDecimal output = new BigDecimal(Float.toString(Integer.parseInt(hhStr)));
output = output.add((inputBD.subtract(output).divide(BigDecimal.valueOf(60), 10, BigDecimal.ROUND_HALF_EVEN)).multiply(BigDecimal.valueOf(100)));
return Float.parseFloat(output.toString());
}
public static String convertTo60(float input)
{
String input_string = Float.toString(input);
BigDecimal inputBD = new BigDecimal(input_string);
String hhStr = input_string.split("\\.")[0];
BigDecimal output = new BigDecimal(Float.toString(Integer.parseInt(hhStr)));
output = output.add((inputBD.subtract(output).divide(BigDecimal.valueOf(100), 2, BigDecimal.ROUND_HALF_EVEN)).multiply(BigDecimal.valueOf(60)));
return output.toString().replace(".",":");
}
}
What am I doing wrong?
Thanks!
in your convertTo60 switch the order of divide and multiply operations.
In porting an algorithm from JavaScript to Java, I've run into the problem that I need a replacement for JavaScript's toPrecision(). The problem is that I don't have a clue how small or large the numbers will be, so I can't use a simple NumberFormat with the right format.
Is there a standard class that offers a similar functionality?
EDIT
Here is what I came up with:
double toPrecision(double n, double p) {
if (n==0) return 0;
double e = Math.floor(Math.log10(Math.abs(n)));
double f = Math.exp((e-p+1)*Math.log(10));
return Math.round(n/f)*f;
}
In principle, it does the right thing, but rounding errors completely ruin it. For example,
toPrecision(12.34567, 3) returns 12.299999999999997
EDIT 2
This version works perfectly for 11 out of 12 test cases...
double toPrecision(double n, double p) {
if (n==0) return 0;
double e = Math.floor(Math.log10(Math.abs(n)));
double f = Math.round(Math.exp((Math.abs(e-p+1))*Math.log(10)));
if (e-p+1<0) {
f = 1/f;
}
return Math.round(n/f)*f;
}
But toPrecision(0.00001234567, 3) still returns 1.2299999999999999E-5 instead of 1.23E-5
Use BigDecimal and setScale() method to set the precision
BigDecimal bd = new BigDecimal("1.23456789");
System.out.println(bd.setScale(3,BigDecimal.ROUND_HALF_UP));
Output
1.235
See
IDEone demo
The simplest solution I came up with for this uses a combination of java.math.BigDecimal and java.math.MathContext like so.
String toPrecision(double number, int precision) {
return new BigDecimal(number, new MathContext(precision)).toString();
}
I'm using this in the dynjs implementation of Number.prototype.toPrecision.
Here's a java solution using String.format.
public static String toPrecision(double d, int digits) {
s = String.format("%."+((digits>0)?digits:16)+"g",d).replace("e+0","e+").replace("e-0","e-");
return s;
}
The .replace is only needed if you want to mimic javascript where it has no leading zero on exponents. If you are just using it for a rounding then return the value as
return Double.parseDouble(s);
Here is some unit test code:
public void testToPrecision() {
String s = NumberFormat.toPrecision(1234567.0,5);
assertEquals("1.2346e+6",s);
s = NumberFormat.toPrecision(12.34567,5);
assertEquals("12.346",s);
s = NumberFormat.toPrecision(0.1234567,5);
assertEquals("0.12346",s);
s = NumberFormat.toPrecision(0.1234567e20,5);
assertEquals("1.2346e+19",s);
s = NumberFormat.toPrecision(-0.1234567e-8,5);
assertEquals("-1.2346e-9",s);
s = NumberFormat.toPrecision(1.0/3.0,5);
assertEquals("0.33333",s);
s = NumberFormat.toPrecision(1.0/3.0,0);
assertEquals("0.3333333333333333",s);
}
You can use double with
double d = 1.23456789;
System.out.println(Math.round(d * 1e3) / 1e3);
prints
1.235
or
System.out.printf("%.3f%n", d);
does the same.
public static void main(String... args) {
System.out.println(round3significant(12345678.9));
System.out.println(round3significant(0.0000012345));
}
public static double round3significant(double d) {
if (d < 100) {
double divide = 1;
while(d < 100) {
d *= 10;
divide *= 10;
}
return Math.round(d) / divide;
} else {
double multi = 1;
while(d > 1000) {
d /= 10;
multi *= 10;
}
return Math.round(d) * multi;
}
}
prints
1.23E7
1.23E-6
You can use NumberFormat to only display as a decimal.
This finally works...
double toPrecision(double n, double p) {
if (n==0) return 0;
double e = Math.floor(Math.log10(Math.abs(n)));
double f = Math.round(Math.exp((Math.abs(e-p+1))*Math.log(10)));
if (e-p+1<0) {
return Math.round(n*f)/f;
}
return Math.round(n/f)*f;
}
import java.text.*;
Class Decimals
{
public static void main(String[] args)
{
float f = 125.069f;
DecimalFormat form = new DecimalFormat("#.##");
System.out.println(form.format(f));
}
}
.## represents upto what decimal places you want
I hope this suits your requirement.
it give me an error when choosing "Positive improper integration"or"Negative improper integration"
the error is Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
at java.math.BigDecimal.divide(BigDecimal.java:1603)
at SE_Project_2.calculate(SE_Project_2.java:55)
at SE_Project_2.main(SE_Project_2.java:45)
Code:
import java.math.BigDecimal;
import javax.swing.JOptionPane;
public class SE_Project_2 {
private static BigDecimal C0 = new BigDecimal("0.1713245");
private static BigDecimal C1 = new BigDecimal("0.3607616");
private static BigDecimal C2 = new BigDecimal("0.4679139");
private static BigDecimal C3 = new BigDecimal("0.4679139");
private static BigDecimal C4 = new BigDecimal("0.3607616");
private static BigDecimal C5 = new BigDecimal("0.1713245");
private static BigDecimal X0 = new BigDecimal("-0.932469514");
private static BigDecimal X1 = new BigDecimal("-0.661209386");
private static BigDecimal X2 = new BigDecimal("-0.238619186");
private static BigDecimal X3 = new BigDecimal("0.238619186");
private static BigDecimal X4 = new BigDecimal("0.661209386");
private static BigDecimal X5 = new BigDecimal("0.932469514");
private static BigDecimal a=new BigDecimal("0"),b=new BigDecimal("0");
private static int y;
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
try{
String[] o = {"Positive improper integration","Negative improper integration","Normal integration"};
y = JOptionPane.showOptionDialog(null,"Welcome to my program! \nYahya Al-Buluwi\nIt can work for big decimal numbers.\n\nThis program will find the integral of: \nf(x)= 5x + 3 dx\nBy using the 6-points Gauss Legendre Quadrature formulae.\n\n What choise is prefered to you?","Welcome",JOptionPane.YES_NO_CANCEL_OPTION,JOptionPane.QUESTION_MESSAGE,null,o,o[2]);
BigDecimal sum = null;
if (y==2){
a = new BigDecimal((String)JOptionPane.showInputDialog(null,"Enter the value of a:","Enter the value of a", JOptionPane.QUESTION_MESSAGE));
b = new BigDecimal((String)JOptionPane.showInputDialog(null,"Enter the value of b:","Enter the value of b", JOptionPane.QUESTION_MESSAGE));
}
sum = calculate(X0,C0).add(calculate(X1,C1).add(calculate(X2,C2)).add(calculate(X3,C3).add(calculate(X4,C4).add(calculate(X5,C5)))));
System.out.println("y=" + y);
JOptionPane.showMessageDialog(null,"The 6-points Gauss Legendre Quadrature formulae solution according to \na= " + a+"\nb= "+b+" \nis: "+ sum,"Result",JOptionPane.INFORMATION_MESSAGE);
}catch(Exception e){
JOptionPane.showMessageDialog(null,"Ooops! an error has occured! the program will be terminated.","Error",JOptionPane.ERROR_MESSAGE);
calculate(X0,C0).add(calculate(X1,C1).add(calculate(X2,C2)).add(calculate(X3,C3).add(calculate(X4,C4).add(calculate(X5,C5)))));
System.out.println("y=" + y);
JOptionPane.showMessageDialog(null,"The 6-points Gauss Legendre Quadrature formulae solution according to \na= " + a+"\nb= "+b+" \nis: "+ calculate(X0,C0).add(calculate(X1,C1).add(calculate(X2,C2)).add(calculate(X3,C3).add(calculate(X4,C4).add(calculate(X5,C5))))),"Result",JOptionPane.INFORMATION_MESSAGE);
}
}
public static BigDecimal calculate(BigDecimal x, BigDecimal c){
BigDecimal h = x.multiply(new BigDecimal("0.5"));
if(y==0){
// PI= (1/(.5x)**2)*((5/(.5+.5x))+3)
return (((new BigDecimal("1")).divide(h.pow(2))).multiply((new BigDecimal("3")).add((new BigDecimal("5")).divide((new BigDecimal("0.5")).add(h)))));
}
if(y==1){
// NI= (1/(-.5x)**2)*((5/(-.5-.5x))+3)
return ((new BigDecimal("1").divide((h.negate()).pow(2))).multiply(new BigDecimal("3").add(new BigDecimal("5").divide(new BigDecimal("-0.5").add(h.negate())))));
}
BigDecimal sum = (b.add(a)).divide(new BigDecimal("2"));
BigDecimal diff =(b.add(a.negate())).divide(new BigDecimal("2"));
return c.multiply(diff.multiply((((diff.multiply(x)).add(sum)).multiply(new BigDecimal("5"))).add(new BigDecimal("3"))));
}
}
You probably need to use one of the divide methods that specify the rounding mode.
Read also here.
This happens when you do 1/3 on BigDecimal and don't specify how precise the result should be and what the round method should be like.
See javadoc (http://download.oracle.com/javase/6/docs/api/java/math/BigDecimal.html)
You may use a MathContext object to wrap up precision and roundupMethod together. You may also choose to specify it directly. Add that information to constructor or when calling divide are both ok.
Divide method throws this exception if the resulting number have infinite decimal expansion. In this case, you need to provide a MathContext, which will define how the number will be rounded, so that it have a finite value.
How to convert hexadecimal string to single precision floating point in Java?
For example, how to implement:
float f = HexStringToFloat("BF800000"); // f should now contain -1.0
I ask this because I have tried:
float f = (float)(-1.0);
String s = String.format("%08x", Float.floatToRawIntBits(f));
f = Float.intBitsToFloat(Integer.valueOf(s,16).intValue());
But I get the following exception:
java.lang.NumberFormatException: For input string: "bf800000"
public class Test {
public static void main (String[] args) {
String myString = "BF800000";
Long i = Long.parseLong(myString, 16);
Float f = Float.intBitsToFloat(i.intValue());
System.out.println(f);
System.out.println(Integer.toHexString(Float.floatToIntBits(f)));
}
}
You need to convert the hex value to an int (left as an exercise) and then use Float.intBitsToFloat(int)