Being pedantic, < 0 won't give you all negative numbers.
double d = -0.0;
System.out.println(d + " compared with 0.0 is " + Double.compare(d, 0.0));
System.out.println(d + " < 0.0 is " + (d < 0.0));
prints
-0.0 compared with 0.0 is -1
-0.0 < 0.0 is false
-0.0 is negative but not less than 0.0
You can use
public static boolean isNegative(double d) {
return Double.compare(d, 0.0) < 0;
}
A more efficient, if more obtuse, version is to check the signed bit.
public static boolean isNegative(double d) {
return Double.doubleToRawLongBits(d) < 0;
}
Note: Under IEEE-754 a NaN can have the same signed bit as a negative number.
Answer from Peter Lawrey on Stack OverflowBeing pedantic, < 0 won't give you all negative numbers.
double d = -0.0;
System.out.println(d + " compared with 0.0 is " + Double.compare(d, 0.0));
System.out.println(d + " < 0.0 is " + (d < 0.0));
prints
-0.0 compared with 0.0 is -1
-0.0 < 0.0 is false
-0.0 is negative but not less than 0.0
You can use
public static boolean isNegative(double d) {
return Double.compare(d, 0.0) < 0;
}
A more efficient, if more obtuse, version is to check the signed bit.
public static boolean isNegative(double d) {
return Double.doubleToRawLongBits(d) < 0;
}
Note: Under IEEE-754 a NaN can have the same signed bit as a negative number.
Double v = (Double.parseDouble(data[2]));
if (v<0){
//do whatever?
}
I don't know what the exact issue is here, but use BigDecimal (instead of double) when working with money.
I suggest you step through your code using a debugger and you would see how your values are actually changing.
Your negative interest is interest_neg = -0.002. which you multiply by your amount.
Say you have the following situation
double balance = -100;
if ( balance >= 0 ) balance *= interest_pos;
else balance *= interest_neg; // balance = -100 * -0.002 = +0.2
A negative interest doesn't make any sense of this value as you can see. If I had a million dollar debt, the next month I would have $200. The more in debt I am the more money I will have next month.
So whenever you have a negative balance you are making it positive again. Perhaps your negative interest should be 1.002, similar to your positive interest.
else balance *= interest_neg; // balance = -100 * 1.002 = -100.2
(int)1700 * (int)1944038 is equal to your -990102696.
Are you sure c12 and fileSize aren't integers? If they are, the multiplication occurs with integer types, integer overflow and it is being promoted to double afterwards.
Your c12 and fileSize are most likely ints (+1 Tomasz). Java multiplies the ints, which overflows, becoming negative, and then stores that negative value in your double. Cast c12 and fileSize to double before multiplying:
double c12 = 1700, fileSize = 1944038;
System.out.println(c12 * fileSize);
produces:
3.3048646E9
public static double toDouble(String a){
int sign = 1;
int start = 0;
if(a.charAt(0) == '-'){
start = 1;
sign = -1;
}
double value = 0;
boolean decimal = false;
int exp = 0;
for(int i = start; i < a.length(); i++){
if(a.charAt(i) == '.'){
if(decimal) return 0.0;
decimal = true;
}else{
value += (a.charAt(i) - 48) * Math.pow(10,a.length() - i - 1);
}
if(decimal) exp++;
}
value = value / Math.pow(10,exp);
value *= sign;
System.out.println(value);
return value;
}
I sort of rewrote it the way i would do this problem. If you remember i posted psuedo code on your other question this is my "programmed" version.
This is how my code works.
First it checks the sign at the first character [0] then increments the start position to 1 instead of zero to start the loop past the - sign.
It loops through the array and checks to see if there is a . if it is it sets the decimal variable to true instead of false. If it reads more than one decimal point in the string it will return a 0.0 which i denoted as a fail value. However, if it doesn't pick up anymore decimals it increments the exponent value to see how many spaces it will need to jump.
value += (a.charAt(i) - 48) * Math.pow(10,a.length() - i - 1);
this line of code is very interesting. a.charAt(i) - 48 converts the character to an integer value.
then i multiply it by 10^(what power of ten the value is at then subtract one to compensate for 1.0). Then i add it value.
Everything else is pretty self explanatory.
NOTE:
I tested this code myself, however one important thing is that i haven't added checks for invalid strings with other characters.
int g=0,fnl=0;
String input = "-12.0";
String temp = input;
String forDecimalPart = input;
if(input.charAt(0)=='-') {
temp=input.substring(1);
}
int exp = temp.indexOf(".");
System.out.println(exp);
int d=0;
while(temp.charAt(d)!='.') {
g=temp.charAt(d)-48;
int k = 1;
for(int f=1;f<exp;f++) {
k*=10;
}
fnl+=(k*g);
d++;
exp--;
System.out.println(fnl);
}
forDecimalPart=temp.substring(d) ;
double num1= Double.parseDouble(forDecimalPart);
double finalnum=(fnl+num1);
if(input.charAt(0)=='-'){
finalnum*=-1;
}
System.out.println(finalnum);
i have given you the answer as you have put the effort to come up with atleast this code. good luck :) I have scripted the code resembling your question without adding any Extra methods from other classes like Math.pow()
I'm not sure what result you would like, but the result for 2.0 is absolutely correct.
Note that the number it gives is not zero padded, so it may seem to have the sign bit set, but the bit set is the highest bit of the exponent.
Floating point values (such as double) are represented completely different from integer values. From integer values you are used to them being represented as a zero-padded (for positive numbers) binary number which represents the same number in base 2. This does not hold true for floating point values.
By definition floating point values have a floating decimal point, so the binary number has to encode the information on where the decimal point is. This is done by reshaping the number to the following:
(+/-) x * 2^y whereas 0 <= x < 2 (= 10 base 2)
(+/-) is the sign which takes one bit. x is the mantissa, y the exponent. So the binary representation has to encode three pieces in the end.
Since 0 <= x < 2, x always starts with 1.something, so the 1. need not be in the representation. Only the part after the decimal point is saved, which is considered the significand.
In your example, 2.0 is reshaped to:
+ 1.0 * 2 ^ 1
Sign: + Significand: 0 Exponent: 1
This happens to be represented as
0 10000000000 0000000000000000000000000000000000000000000000000000
For negative numbers the sign is - which is represented as a leading 1:
1 10000000000 0000000000000000000000000000000000000000000000000000
Note that your original posts lists a number that is missing the leading 0 which is mathematically correct but misleading when you try to capture the binary representation:
10000000000 0000000000000000000000000000000000000000000000000000 =
0 10000000000 0000000000000000000000000000000000000000000000000000
There are some more details to understand and keep in mind. For example the exponent can be negative, too. You can find a more elaborate explanation in the Floating Point Wikipedia article. binaryconvert.com as referenced by Joachim can also help you understand the representation.
A formula that is supposed to give a distance should have a real, not imaginary, result for all applicable inputs.
Raising a negative number to a fractional power has an imaginary number result. Java double is an approximation to the real numbers. Java Math functions return NaN whenever the result would be imaginary.
Raising a negative number to an even integer power gives a positive result. Raising a negative number to an odd integer power gives a negative result.
You prefer the results for the even integer values of z, corresponding to odd integer values of z-25. The better behaved formula -Math.pow(1.1, -(z - 25)) + 10.8347 matches for those inputs, but you need to rethink the theory underlying your formula.
-10.0 : -17.26773684806433
-8.5 : -13.524047455696502
-7.0 : -10.279076745352606
-5.5 : -7.466387494888428
-4.0 : -5.028392971714952
-2.5 : -2.91517790750445
-1.0 : -1.0834765377272344
0.5 : 0.5042132175022935
2.0 : 1.8803975674476092
3.5 : 3.0732523797913576
5.0 : 4.107200050674389
6.5 : 5.00340952651492
8.0 : 5.780229715007055
9.5 : 6.453565158914292
11.0 : 7.037201664167585
12.5 : 7.543088549146725
14.0 : 7.981583293889997
15.5 : 8.36166359815682
17.0 : 8.691111189999997
18.5 : 8.976671148126837
20.0 : 9.22419
i figured it out by changing the negatives from
Math.pow(-1.1, -(z-25))+10.8347
to
-(Math.pow(1.1, -(z-25))-10.8347)
somehow it let all the answers work
After bidAmount = Double.parseDouble(messageToServer);, we need to add the following:
if(bidAmount < 0){
throw new NumberFormatException("Invalid amount");
}
An alternate solution (and probably, best practice) would be to modify catch block to catch IllegalArgumentException and throw IllegalArgumentException if the amount is less than 0 as shown below:
try
{
//convert number to double (monetary value)
bidAmount = Double.parseDouble(messageToServer);
if(bidAmount < 0){
throw new IllegalArgumentException("Invalid amount");
}
//send to server with item code
output.println(selectedItemCode + bidAmount);
}
//item cannot turned to double
catch (IllegalArgumentException numfEx)
{
//inform user
fromServer.setText("Invalid Request!"
+ USER_PROMPT);
}
This can be achieved without relying on exceptions to control the flow of your program, which is generally a bad idea - see discussion here
else {
// using a tempBidAmount as I don't have enough context to know whether
// I could just assign the output of parseUserDouble directly to bidAmount
// without causing issues
Double tempBidAmount = parseUserDouble(messageToServer);
if (tempBidAmount != null && tempBidAmount > 0.0) {
bidAmount = tempBidAmount;
output.println(selectedItemCode + bidAmount);
} else {
fromServer.setText("Invalid Request!" + USER_PROMPT);
}
}
toServer.setText("");
....
private Double parseUserDouble(Sting userInput) {
try {
return Double.parseDouble(userInput);
}
catch (NumberFormatException numfEx) {
// consider logging here
}
return null;
}
You can explicitly handle the negative zero case:
roundedValue = (roundedValue == 0.0 && 1 / roundedValue < 0) ? 0 : roundedValue;
(1 / roundedValue < 0 to check for negative zero, from this answer)
Nit: use Double.parseInt rather than valueOf, to avoid the unnecessary boxing and immediate unboxing.
First, you have to realize that double values are semantically different from integers. They are imprecise, so there is always ever-so-slight error in every double value. The error, however, is small, but in unfortunate case it could be on the other side of zero - technically correct, but not what you want. This understanding is essential; if you need digit-exact arithmetic, you shouldn't be using doubles anyway, but integers/longs. Part of IEEE specification for double values also defines "negative zero", "NaN", "infinity" and so on, so technically the software is correct, but you are not using it the right way for what you want to achieve.
Second, like other people already mentioned, never use string formatting for rounding. If you need 4 decimal places, a much better way is to multiply the number by 10000, take floor/round of it and divide it by 10000 again. However, due to the facts mentioned above, you might again get some small decimal off (such as the 15th decimal digit).
On the other hand, if you just want to get rid of "rounding noise" which is sufficiently close to zero, you can also use this approach which is very robust:
if (Math.abs(x) < 0.000001d) x = 0d;
The integer cases are easy. The double case is trickier, until you remember about infinities.
Note: If you consider the double constants "part of the api", you can replace them with overflowing expressions like 1E308 * 2.
int sign(int i) {
if (i == 0) return 0;
if (i >> 31 != 0) return -1;
return +1;
}
int sign(long i) {
if (i == 0) return 0;
if (i >> 63 != 0) return -1;
return +1;
}
int sign(double f) {
if (f != f) throw new IllegalArgumentException("NaN");
if (f == 0) return 0;
f *= Double.POSITIVE_INFINITY;
if (f == Double.POSITIVE_INFINITY) return +1;
if (f == Double.NEGATIVE_INFINITY) return -1;
//this should never be reached, but I've been wrong before...
throw new IllegalArgumentException("Unfathomed double");
}
The following is a terrible approach that would get you fired at any job...
It depends on you getting a Stack Overflow Exception [or whatever Java calls it]... And it would only work for positive numbers that don't deviate from 0 like crazy.
Negative numbers are fine, since you would overflow to positive, and then get a stack overflow exception eventually [which would return false, or "yes, it is negative"]
Boolean isPositive<T>(T a)
{
if(a == 0) return true;
else
{
try
{
return isPositive(a-1);
}catch(StackOverflowException e)
{
return false; //It went way down there and eventually went kaboom
}
}
}
The IEEE 754 format has one bit reserved for the sign and the remaining bits representing the magnitude. This means that it is "symmetrical" around origo (as opposed to the Integer values, which have one more negative value). Thus the minimum value is simply the same as the maximum value, with the sign-bit flipped, so yes, -Double.MAX_VALUE is the lowest actual number you can represent with a double.
I suppose the Double.MAX_VALUE should be seen as maximum magnitude, in which case it actually makes sense to simply write -Double.MAX_VALUE. It also explains why Double.MIN_VALUE is the least positive value (since that represents the least possible magnitude).
But sure, I agree that the naming is a bit misleading. Being used to the meaning Integer.MIN_VALUE, I too was a bit surprised when I read that Double.MIN_VALUE was the smallest absolute value that could be represented. Perhaps they thought it was superfluous to have a constant representing the least possible value as it is simply a - away from MAX_VALUE :-)
(Note, there is also Double.NEGATIVE_INFINITY but I'm disregarding from this, as it is to be seen as a "special case" and does not in fact represent any actual number.)
Here is a good text on the subject.
These constants have nothing to do with sign. This makes more sense if you consider a double as a composite of three parts: Sign, Exponent and Mantissa. Double.MIN_VALUE is actually the smallest value Mantissa can assume when the Exponent is at minimun value before a flush to zero occurs. Likewise MAX_VALUE can be understood as the largest value Mantissa can assume when the Exponent is at maximum value before a flush to infinity occurs.
A more descriptive name for these two could be Largest Absolute (add non-zero for verbositiy) and Smallest Absolute value (add non-infinity for verbositiy).
Check out the IEEE 754 (1985) standard for details. There is a revised (2008) version, but that only introduces more formats which aren't even supported by java (strictly speaking java even lacks support for some mandatory features of IEEE 754 1985, like many other high level languages).
or is there other magic here?
Yes. 2's complement.
2's complement is a bit magical. It accomplishes 2 major objectives. Before getting into that, let's first stew on the notion of negative zero for a moment.
Negative zero is kinda weird. Why does it exist at all?
Negative zero isn't actually a thing. Ask any mathematician "Hey, so, what's up with negative zero?" and they'll just look at you in befuddlement. It's not a thing. Mathematically, 0 and -0 are utterly identical. Not just 'nearly identical', but 100%, fully, in all possible ways, identical. We don't generally want our numbers to be capable of representing both 5.0 as well as 5.00 - as those two are entirely, 100%, identical. If you don't think that a value system ought to waste bits trying to differentiate between 5.0 and 5.00, then it's equally bizarro to want the ability to represent -0.0 and +0.0 as distinct entities.
So, wanting -0 in the first place is kinda weird. All the numeric primitives (long, int, short, byte, and I guess char which is technically numeric too) all cannot represent this number. Instead, long z = -0 boils down to:
- Take the constant "0".
- Apply the 'negate' operation to this number (
-is a unary operator. Just like2+5makes the system calculate the binary operation of "addition" on elements 2 and 5,-xmakes the system calculate the unary operation of "negation" on elementx. Applying the negation operation to 0 produces 0. It's no different from writing, say,int x = 5 + 0;. That+0part doesn't do anything. The-in front of-0doesn't do anything. In contrast to-0.0where it does do something (gets you negative zero, thedoublevalue, instead of positive zero). - Store this result in
z(so, just 0 then).
There is no way to tell if that minus is there. They both result in ALL ZERO bits, and hence, there is no way for the computer to tell if you initialized that variable with the expression -0 or with +0. Again in contrast to double where as you noticed there's a bit different.
So why does double have it then?
Let's stew a bit on the notion of doubles and IEEE-754 math.
A double takes 64 bits. From basic pure mathematical principles then, a double is as incapable of representing more than 2^64 different possible values you are capable of breaking the speed of light or making 1+1=3.
And yet, a double aims to represent all numbers. There are way more numbers between 0 and 1 than 2^64 options (in fact, an infinite amount of numbers exist between 0 and 1), and that's just 0 to 1.
So, how doubles actually work is different. A few less than 2^64 numbers are chosen from the entire number line. Let's call these the blessed numbers.
The blessed numbers are not equally distributed. The closer you are to 1, the more blessed numbers exist. In other words, the distance between 2 blessed numbers increases as you move away from 1. For example, if you go from, say, 1e100 (a 1 with a hundred zeroes) and want to find the next blessed number, it's quite a ways. It's in fact higher than 1.0! - 1e100+1 is in fact 1e100 again, because the way double math works is that after every single last mathematical operation you to do them, the end result is rounded to the nearest blessed number.
Let's try it!
double d = 1e100;
System.out.println(d);
System.out.println(d + 1);
// prints: 1.0E100
// 1.0E100
But that means.. double values don't actually represent a single number!!. What any given double represents is in fact this concept:
An unknown number whose value lies between [D - 𝛿, D + 𝛿], where D is the blessed number that is closed to this unknown number this value represents, and, and 𝛿 is half of the distance between D and the next nearest blessed number on either side.
Given that usually 𝛿 is incredibly small, this is 'good enough'. But this weirdness does explain why you really, really do not want any business at all with double if accuracy is important (such as with currencies. Don't store those in doubles, ever!)
Given that, what does -0.0 represent? not actually just 0. It represents, specifically: An unknown number whose value lies between [-𝛿, 0] where 0 is real zero (and this, has no sign), and 𝛿 is Double.MIN_VALUE: the smallest non-zero positive number representable with a double.
That's why -0.0 and +0.0 both exist: They are in fact different concepts. Rarely relevant, but sometimes it is. In contrast to e.g. long where 5 just means 5 and not "between 4.5 and 5.5", because longs fundamentally don't recognize that fractional parts exist in the first place. Given that 5 just means 5, then 0 just means 0, and there is no such thing as negative zero in the first place.
Now we get to 2's complement
2's complement is a cool system. It has two neat properties:
- It only has the one zero.
- It does not matter if you treat the bit sequence as signed-by-way-of-2s-complement or as unsigned, for the purposes of the operations: Addition, Substraction, Increment, Decrement, zero-check. The modifications you do to the bits to implement those operations is identical.
It DOES matter for greater than, less than, and divide.
2's complement works like this: To negate a number, take all bits and flip them (i.e. do a NOT operation on the bits). Then, add 1.
Let's try it!
int x = 5;
int y = -x;
for (int i = 31; i >= 0; i--) {
System.out.print((x >>> i) & 1);
}
System.out.println();
for (int i = 31; i >= 0; i--) {
System.out.print((y >>> i) & 1);
}
System.out.println();
// prints 00000000000000000000000000000101
// 11111111111111111111111111111011
As we can see, the 'flip all bits and add 1' algorithm was applied.
2s complement is, of course, reversible: If you do 'flip all bits and add 1' twice in a row you get the same number out.
Now let's try -0. 0 is 32 0 bits, then flip them all, then add 1:
00000000000000000000000000000000
11111111111111111111111111111111 // flip all
100000000000000000000000000000000 // add 1
00000000000000000000000000000000 // that 1 fell off
and because ints can only store 32 bits, that final '1' falls off of the end. And we're left with zero again.
Now let's go with bytes ( abit smaller) and try to add, say, 200 and 50 together.
11001000 // 200 in binary
00110010 // 50 in binary
-------- +
11111010 // 250 in binary.
now let's instead go: Oh wait, whoops, that was an error, actually these numbers are in 2s complement. That wasn't 200, nono. 11001000 is a bit sequence that actually means (let's apply the 'flip all bits, add 1' scheme: 00111000 - it's actually -56. So the operation was meant to represent '-56 + 50'. Which is -6. -6 in binary is (write out 6, flip bits, add 1):
00000110
11111001
11111010
hey now, look at that, nothing changed! It's the same result! So, when the computer does x + y, where x and y are numbers, the computer does not care. Whether x is "an unsigned number" or "a signed with 2s complement number", the operation is identical.
That's why 2s complement is applied. It makes math MUCH faster. The CPU doesn't have to futz about with branching out to deal with sign bits.
In this sense it is more correct to say that in java, int, long, char, byte and short are neither signed nor unsigned, they just are. At least for the purposes of +, -, ++, and --. No the idea that int is signed is fundamentally a property of e.g. System.out.println(int) - that method chooses to render the bitsequence 11111111111111111111111111111111 as "-1" instead of as 4294967296.
long has no such thing as negative zero. Only float and double have a different representation of positive and negative zero.
Why are these two exceptions necessary to "allow hash tables to operate properly"?
In fact, that statement is a bit misleading. It would be more accurate to say that those exceptions in the definition of Double.equals() are necessary for the chosen implementation of Double.hashCode() to be consistent with equals(). That characteristic is indeed relevant to the Java platform library's hash implementations. You'll find a great deal of verbiage devoted to that topic generally, both on SO and elsewhere. For example:
- What issues should be considered when overriding equals and hashCode in Java?
- How to use java.Set
- Why do I need to override the equals and hashCode methods in Java?
Since the general topic of hashCode() / equals() consistency is so well covered, I'll focus on how they apply to class Double. There are several details in this area that it is necessary to understand:
- Java
Doubleis the wrapper class fordouble, anddoubleis defined in terms of IEEE-754 binary double precision format. - In IEEE-754, positive and negative zero are distinct values. Even though they compare equal to each other, they have different bit patterns, and they are distinguishable by some of their other properties. This is useful and desirable for some purposes.
- On the other hand, although IEEE-754 defines several "not a number" (NaN) bit patterns, Java uses only one of them.
- IEEE-754 specifies that its special NaN values compare unequal to every value, including themselves. This is one of their distinguishing features.
Double.hashCode()is defined in terms of arithmetic operations on the bit pattern of the wrappeddouble.
Because Double.hashCode() is computed from the wrapped double's bit pattern, and the bit patterns of positive and negative zero differ, the hash codes of Double(+0.0) and Double(-0.0) differ. That would make this hashCode() implementation inconsistent with equals() if two such Double instances compared equal. Therefore, Double.equals() is defined so that they do not compare equal. That was not the only alternative: hashCode() could have instead been defined so that the two flavors of zero had the same hash code.
On the flip side, because Java provides only one NaN value of type double, with its specific bit pattern, Double instances representing that value yield the same hash code. Although again this follows from the chosen implementation of hashCode(), there would be no easy way to mirror IEEE-754 equality semantics in class Double, because doing so would need to violate an even more important invariant than equals() being consistent with hashCode(): equals being reflexive. That is, it is expected always to be the case that for any non-null reference a, a.equals(a) is true.
The first bullet point is necessary to meet the contract for equals and hash code (which is what HashTable/HashMap uses). Specifically, any object must be equal to itself, per the equals Javadoc:
The equals method implements an equivalence relation on non-null object references:
- It is reflexive: for any non-null reference value
x,x.equals(x)should returntrue.
Since a hash code is required to be consistent with the behavior of the equals method, this applies to hashCode as well.
If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
Therefore, at a minimum, the same NaN Double object must be equal to itself. Technically, it wouldn't be required that different instances of Double with the NaN value must be equal to each other. My guess is they made all NaN values equal because it would be confusing if the weren't, and inconsistent with the fact that Double is basically a value type, so identity equality would be inappropriate.
I can't think of a reason why the second exception is necessary to allow hash tables to operate properly, however.
Here's an example (.NET syntax, should be OK in Java too):
^[+-]?(([1-9]\d*)|0)(\.\d+)?
Basically, this has an optional + or - symbol followed by either 0 or a number from 1 - 9 followed by an arbitrary number of digits. Optionally, it can contain a decimal point followed by one or more numbers.
The important thing about this regex (and this is what addresses your problem) is that it has the added restriction that multi-digit numbers can't start with 0 - you can have something that equals exactly 0, but you can't have something like 000010.1 or 0000.0 or anything like that. Something like 0 or 0.0 or 100.1 would be OK.
Here is another alternative, which handles exponents, if you want them:
^[+-]?([1-9][0-9]*|0)(\.[0-9]+)?((e|E)[+-]?[0-9]+)?$
I just now realised, that it essentially is the same as @EJoshuaS' with the exponent addition.
Here is a link to verify it:
https://regex101.com/r/WEaNLR/4