float -> double

W

wx

float f = 1.234567;
double d = f;
System.out.println(f + ", " + d);
--->
1.234567, 1.2345670461654663

What is the cleanest way to deal with this? One solution is:
double d = Double.parseDouble(Float.toString(f));

but I don't like it too much (though it works completely OK).

I don't want rounding or any other things that would interfere with
the result in any way (i.e. I want f == d exactly, without guessing
about the properties of the number stored in f). Any other & better
solution?
 
S

Simon

wx said:
float f = 1.234567;
double d = f;
System.out.println(f + ", " + d);
--->
1.234567, 1.2345670461654663

What is the cleanest way to deal with this? One solution is:
double d = Double.parseDouble(Float.toString(f));

but I don't like it too much (though it works completely OK).

I don't want rounding or any other things that would interfere with
the result in any way (i.e. I want f == d exactly, without guessing
about the properties of the number stored in f). Any other & better
solution?

Deal with what?

Consider this code:

float f = 1.234567f; // won't compile without the "f"
double d1 = f;
double d2 = Double.parseDouble(Float.toString(f));
System.out.println(d1 == f);
System.out.println(d2 == f);

outputs

true
false

So, the first solution (which is what you presented as the problematic code)
precisely matches your requirement ("f == d exactly") whereas your own solution
does not. I'm confused about what your problem really is.

Or ist it just how Java formats your numbers? In that case, maybe look at
java.text.NumberFormat

BTW, why would you want to mix float and double and why would you want to
compare them? Could this be a design issue?

Cheers,
Simon
 
P

Patricia Shanahan

wx said:
float f = 1.234567;
double d = f;
System.out.println(f + ", " + d);
--->
1.234567, 1.2345670461654663

What is the cleanest way to deal with this? One solution is:
double d = Double.parseDouble(Float.toString(f));

but I don't like it too much (though it works completely OK).

I don't want rounding or any other things that would interfere with
the result in any way (i.e. I want f == d exactly, without guessing
about the properties of the number stored in f). Any other & better
solution?

Exact conversion is what you did get, and if you do anything like the
parseDouble manipulation you will lose that. The default conversion of
float or double to a string does rounding that depends on the type being
converted. Fewer digits are printed for float than for double.

The easiest way to see the exact value of a float or double is to
convert it to BigDecimal:

import java.math.BigDecimal;

public class FloatToDoubleTest {
public static void main(String[] args) {
float f = 1.234567f;
double d = f;
System.out.println(f + ", " + d);
System.out.printf("Double %s, Float %s%n",
new BigDecimal(d).toString(), new BigDecimal(f)
.toString());
System.out.println(d==f);
}
}

Note that d and f are exactly equal.

I suspect that what you really want it exact representation of the
decimal fraction 1.234567. If so, consider using BigDecimal instead of
float or double.

In any case, I strongly advise against having anything to do with float
unless both the following conditions are met:

1. You have a very large array, so that you will benefit from its
memory, cache, and bandwidth efficiency.

2. You have enough knowledge of numerical analysis to be sure your
program will meet its precision requirements using float.

Patricia
 
R

Roedy Green

float f = 1.234567;
double d = f;
System.out.println(f + ", " + d);
--->
1.234567, 1.2345670461654663

What is the cleanest way to deal with this? One solution is:
double d = Double.parseDouble(Float.toString(f));

Deal with what? 0.1 is a repeating fraction in binary.

If you want to display numbers rounded with a fixed number of decimal
places, see http://mindprod.com/applet/converter.html
 
W

wx

All, thanks for the comments, I appreciate them!

@Simon, Patricia
d == f is equal to d == (double)f. new BigDecimal(f) is acutally new
BigDecimal((double)f) - there is no BigDecimal(float) constructor,
just BigDecimal(double). Beware of the internal float -> double
conversion, you don't even see it:

float f = 1.234567f;
double d = 1.2345670461654663;
System.out.println(f == d); // true

What do you think the above would print? The numbers are obviously not
equal. Or, even better, try this:

float f = 1.234567f;
double d = 1.2345670461654663;
double d2 = 1.2345670461654673; // Changed 6 -> 7, second to last.
System.out.println(f == d); // true
System.out.println(f == d2); // false
System.out.println(f == (float)d2); // true

See Joshua's post for an explanation.

@Joshua
I understand what you are talking (at least what is important to the
discussion), but I am not sure that I agree with the assumption:
Which number should we choose? The most logical number is 1 + 2^-23--the same number we put in.
<
For example, when I:
float f = 1.2f;
double d = f;

I did not put the nearest number that can be represented. I put 1.2.
So if the nearest number that can be represented is 1.20000...0<more
non-zero digits> (it should be 1.200000047683... if I understand this
correctly), I don't want d to be the nearest number that can be
represented. Actually, I understand that there is no data in float to
carry this information, so what you say is a meaningful approach with
the given amount of data (i.e. you cannot do any better, whichever
approach you take, since you are limited by the amount of data you
have) - one way or another you will run into situations where it
should have been done in another way.

Having sad that, what I am looking for is what I got with a float ->
string -> double conversion. What I am trying to do is another "most
logical" thing to do. My logic in this case is the following. You are
aware float will never be able to carry more then some limited
precision, which is 23 bits. That translates to 7 or so digits in base
10. I (and most other humans, I presume) read in base 10, not base 2,
so what I want is that when I write "1.2" I really get "1.2" at the
end.

In this case I don't want the internal representation of floating
numbers be something that will change my normal way of work. So to
rephrase my question - is my approach the most correct way to get the
same number into double that >looks to the human< like the float
looks to the human<? I.e. get the float, take only the digits in base
10 that are correct, take the closest value in double range to that
one and put it into d? I am losing digits this way, but I am gaining
more then I am losing - human representation is more important in this
case then 8th and later digits, i.e. then precision. As a side note, I
have to use double at the end (interaction with another system which
takes double as the argument).

Thanks again!
 
P

Patricia Shanahan

wx wrote:
....
10 that are correct, take the closest value in double range to that
one and put it into d? I am losing digits this way, but I am gaining
more then I am losing - human representation is more important in this
case then 8th and later digits, i.e. then precision. As a side note, I
have to use double at the end (interaction with another system which
takes double as the argument).
....

If "human representation is more important than the 8th and later
digits", which strongly implies you are thinking in terms of decimal,
rather than binary representation, *why* are you using float and double
in preference to BigDecimal?

Patricia
 
W

wx

@Patricia
If "human representation is more important than the 8th and later
digits", which strongly implies you are thinking in terms of decimal,
rather than binary representation,
<
I thought this is almost always the case. I find it very reasonable
displaying 1.234567 instead of 1.2345670461654663 when the extra
digits are really not important. On the other hand, you rarely display
in binary.
*why* are you using float and double
in preference to BigDecimal?
<
I'm using the other persons' library which only accepts doubles. I
need to convert float -> double. If I went throught BigDecimal, I'd
gain nothing, since there is no BigDecimal(float) constructor as I
mentioned. So, at the end, BigDecimal doesn't help me at all - if you
find a way it could help me, please let me know.

@Eric
Good one! You had me fooled. I trust you *do* understand why the "obvious" truth is false, right?
<
I wrote my understanding in the post: f == d is (double)f == d. Thus,
you actually convert f to double, yielding the same result (because
this is the same number, as Joshua explained in his post).
 
P

Patricia Shanahan

wx said:
@Patricia
digits", which strongly implies you are thinking in terms of decimal,
rather than binary representation,
<
I thought this is almost always the case. I find it very reasonable
displaying 1.234567 instead of 1.2345670461654663 when the extra
digits are really not important. On the other hand, you rarely display
in binary.

I agree, for display. However, you seem to be trying to impose on
intermediate results the sort of rounding that would normally only be
applied on display. That makes sense in some contexts, such as financial
transactions which have specified rounding rules that have to be applied
at specific stages in the calculation. However, it will generally reduce
the accuracy of the result.
in preference to BigDecimal?
<
I'm using the other persons' library which only accepts doubles. I
need to convert float -> double. If I went throught BigDecimal, I'd
gain nothing, since there is no BigDecimal(float) constructor as I
mentioned. So, at the end, BigDecimal doesn't help me at all - if you
find a way it could help me, please let me know.

Backing up a stage, if you need to impose rounding to a limited number
of decimal digits at intermediate stages, you should probably not be
using a library that operates in double. Conversely, if you should be
using a library that operates in double, why mess with float at all?

Note that it is easy to see that no float can have the exact value
1.234567. That is equivalent to 1234567/1000000, which cannot be
represented as the ratio between an integer and an integer power of two.

Patricia
 
O

Owen Jacobson

I'm using the other persons' library which only accepts doubles. I
need to convert float -> double. If I went throught BigDecimal, I'd
gain nothing, since there is no BigDecimal(float) constructor as I
mentioned.

There is, however, a BigDecimal (String) constructor, which will give
you a BigDecimal representing the exact value you feed it: new
BigDecimal ("1.234567") will not go through float->double conversion
and accrue extra decimal places. Of course, if you convert it to a
double, you'll still get extra decimal places; I'd expect it to return
the double closest to that number, which may well be the one you got.

-o
 
L

Lew

wx said:
@Patricia
digits", which strongly implies you are thinking in terms of decimal,
rather than binary representation,
<
I thought this is almost always the case. I find it very reasonable
displaying 1.234567 instead of 1.2345670461654663 when the extra
digits are really not important. On the other hand, you rarely display
in binary.

Patricia's comment was not about displaying in binary but thinking in binary.

An understanding of binary computation is important for numerical analysis,
the study of how computers do computations. In your original post you stated:
I don't want rounding or any other things that would interfere with
the result in any way

Understanding finite-precision binary representation, one groks that all
floating-point representations in a computer, except for a finite set of
values, are rounded. Therefore rounding will be inevitable when dealing with
'float' and 'double' values. Thinking in terms of binary representation, one
understands why the 'float' value was displayed as 1.234567, but the double
value as 1.2345670461654663.
 
W

wx

Thanks all for being patient!

@Patricia
I agree, for display. However, you seem to be trying to impose on
intermediate results the sort of rounding that would normally only be
applied on display. That makes sense in some contexts, such as
financial
transactions which have specified rounding rules that have to be
applied
at specific stages in the calculation. However, it will generally
reduce
the accuracy of the result.
<
I don't suggest this should be the rule in all (in fact - in any)
calculation. Just commented on the need to present the numbers in the
human readable form. This is always the case AFAIK. Maybe I need to be
more clearer - at the end I don't care if I have 1 kg or
0.9999992304981034 kg of sugar when I leave the grocery store. The
additional information is not just useless, but even harms me (very
unreadable, especially if you have 100s of rows to display, for
example). If somebody needs this (for precise scientific
calculations), that's OK - he should use double. However, if I convert
1 from float to double, I don't want it extended to something else, as
Josh pointed out. Again, I am aware there is not enough information to
"decide" which of the "extension possibilities" to take, but this
still doesn't solve the problem, unfortunately.
Backing up a stage, if you need to impose rounding to a limited number
of decimal digits at intermediate stages,
<
I don't. If I wanted to round, I could use Math.rint(f * 1000000) /
1000000 or something like that. I want float extended to double, but I
just don't want to take what may be the most logical way to extend
float to double. In my case - and I presume a lot of other cases,
extending float to double would be most logically done in base 10, not
base 2. May I call this a mishap that computers don't work in our
base?

@Owen
There is, however, a BigDecimal (String) constructor
<
Sure, but I'd still need float -> string. Taking that into account,
it's just extra work: instead of float -> string -> double, I'd have
to do float -> string -> BigDecimal -> double. I don't need to do any
calculations, so having it in BigDecimal gains me nothing. The only
thing that would be beneficial is if I could go skip the toString step
- it would be a little cleaner solution dealing with numbers only.

@Lew
Patricia's comment was not about displaying in binary but thinking in binary.
An understanding of binary computation is important for numerical analysis,
the study of how computers do computations. In your original post you
stated:
I don't want rounding or any other things that would interfere with
the result in any way

Understanding finite-precision binary representation, one groks that
all
floating-point representations in a computer, except for a finite set
of
values, are rounded. Therefore rounding will be inevitable when
dealing with
'float' and 'double' values. Thinking in terms of binary
representation, one
understands why the 'float' value was displayed as 1.234567, but the
double
value as 1.2345670461654663.
<
I agree with everything. Still, the problem is this:
- You input the number in base 10
- It gets into float f
- I get that float f
- I need to send that as a double d
- To do that, I need to do: double d = (double)f
- Whether the above is explicit or implicit, it will be converted to
the double representation of whatever was stored in float
- The problem is that all values are rounded, as Josh and you noted,
so I don't get the value I wanted, but the nearest possible
- At the end, I need the same number in base 10.

The question is - how do I get this one? May I restate the whole
problem here, after sorting out all the misunderstandings I created.
Say you have this:
- Input a number in base 10
- Store it in a float
- Print this float (to take into account the possibility the number
cannot be represented in float accurately enough)
- Call a method which takes double and returns it's input unmodified
as a double
- Print out the result in base 10
- Confirm that what is displayed is exactly the same as what was
printed in step 3
What are solutions to this? I showed one. Are there others? Why are
they better? Personally, I don't like going through String, that's why
I'm asking at the first place.
 
J

Joshua Cranmer

wx said:
The question is - how do I get this one? May I restate the whole
problem here, after sorting out all the misunderstandings I created.
Say you have this:
- Input a number in base 10
- Store it in a float
- Print this float (to take into account the possibility the number
cannot be represented in float accurately enough)
- Call a method which takes double and returns it's input unmodified
as a double
- Print out the result in base 10
- Confirm that what is displayed is exactly the same as what was
printed in step 3
What are solutions to this? I showed one. Are there others? Why are
they better? Personally, I don't like going through String, that's why
I'm asking at the first place.

Use System.out.printf; that way, you can control how many digits will be
printed.
 
P

Patricia Shanahan

wx wrote:
....
The question is - how do I get this one? May I restate the whole
problem here, after sorting out all the misunderstandings I created.
Say you have this:
- Input a number in base 10
- Store it in a float
- Print this float (to take into account the possibility the number
cannot be represented in float accurately enough)
- Call a method which takes double and returns it's input unmodified
as a double
- Print out the result in base 10
- Confirm that what is displayed is exactly the same as what was
printed in step 3
What are solutions to this? I showed one. Are there others? Why are
they better? Personally, I don't like going through String, that's why
I'm asking at the first place.
....

The simplest solution is to pretend that float does not exist, and
change the flow to:

- Input a number in base 10
- Store it in a double
- Print this double, which is guaranteed to be the closest double to the
original number.
- Call a method which takes double and returns it's input unmodified
as a double
- Print out the result in base 10. Since it was never modified, it will
presumably be identical to the first print out.

Note that if you ever need to compare two floating point numbers that
were produced by non-identical calculations you should allow for a small
difference, due to different rounding.

There are legitimate uses for 32 bit float, though so far I have not met
one in a Java program. On modern processors, float computation is the
same speed as double or only faster in a few rare operations. The main
advantage of float is taking less memory and cache space when dealing
with large arrays. However, if the arrays are big enough for the
difference to be worth worrying about, you would probably need a
numerical analyst to determine if you get enough accuracy from float.

Patricia
 
L

Lew

wx said:
- Print out the result in base 10
- Confirm that what is displayed is exactly the same as what was
printed in step 3
What are solutions to this? I showed one. Are there others? Why are
they better? Personally, I don't like going through String, that's why
I'm asking at the first place.

When you're talking about display or "print", you're talking about
string representations, whether you like it or not.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,431
Messages
2,571,678
Members
48,796
Latest member
Greg L.

Latest Threads

Top