Objects like Integer, String, T[] all have their own unique constructor call. For example, when creating an Integer, instead of putting Integer i = new Integer(5), you can instead put Integer i = 5. Same for String and arrays. I want to know if I could make my own unique replacement for constructor calls. I have a class called Fraction, where you put a numerator and denominator, and it can do whatever a fraction can do. Right now, this is how I construct it: Fraction f = new Fraction(3, 4), where the numerator is the first argument and the denominator is the second. I'm wondering if I could do something like Fraction f = 3/4, where I don't have to call the constructor. Thanks!
You can't add your own literals. The best you could do is a function that parses a literal string.
Fraction f = fraction("3/4");
3/4 will always be the compile-time constant int 0.
Related
I have two Numbers. Eg:
Number a = 2;
Number b = 3;
//Following is an error:
Number c = a + b;
Why arithmetic operations are not supported on Numbers? Anyway how would I add these two numbers in java? (Of course I'm getting them from somewhere and I don't know if they are Integer or float etc).
You say you don't know if your numbers are integer or float... when you use the Number class, the compiler also doesn't know if your numbers are integers, floats or some other thing. As a result, the basic math operators like + and - don't work; the computer wouldn't know how to handle the values.
START EDIT
Based on the discussion, I thought an example might help. Computers store floating point numbers as two parts, a coefficient and an exponent. So, in a theoretical system, 001110 might be broken up as 0011 10, or 32 = 9. But positive integers store numbers as binary, so 001110 could also mean 2 + 4 + 8 = 14. When you use the class Number, you're telling the computer you don't know if the number is a float or an int or what, so it knows it has 001110 but it doesn't know if that means 9 or 14 or some other value.
END EDIT
What you can do is make a little assumption and convert to one of the types to do the math. So you could have
Number c = a.intValue() + b.intValue();
which you might as well turn into
Integer c = a.intValue() + b.intValue();
if you're willing to suffer some rounding error, or
Float c = a.floatValue() + b.floatValue();
if you suspect that you're not dealing with integers and are okay with possible minor precision issues. Or, if you'd rather take a small performance blow instead of that error,
BigDecimal c = new BigDecimal(a.floatValue()).add(new BigDecimal(b.floatValue()));
It would also work to make a method to handle the adding for you. Now I do not know the performance impact this will cause but I assume it will be less than using BigDecimal.
public static Number addNumbers(Number a, Number b) {
if(a instanceof Double || b instanceof Double) {
return a.doubleValue() + b.doubleValue();
} else if(a instanceof Float || b instanceof Float) {
return a.floatValue() + b.floatValue();
} else if(a instanceof Long || b instanceof Long) {
return a.longValue() + b.longValue();
} else {
return a.intValue() + b.intValue();
}
}
The only way to correctly add any two types of java.lang.Number is:
Number a = 2f; // Foat
Number b = 3d; // Double
Number c = new BigDecimal( a.toString() ).add( new BigDecimal( b.toString() ) );
This works even for two arguments with a different number-type. It will (should?) not produce any sideeffects like overflows or loosing precision, as far as the toString() of the number-type does not reduce precision.
java.lang.Number is just the superclass of all wrapper classes of primitive types (see java doc). Use the appropriate primitive type (double, int, etc.) for your purpose, or the respective wrapper class (Double, Integer, etc.).
Consider this:
Number a = 1.5; // Actually Java creates a double and boxes it into a Double object
Number b = 1; // Same here for int -> Integer boxed
// What should the result be? If Number would do implicit casts,
// it would behave different from what Java usually does.
Number c = a + b;
// Now that works, and you know at first glance what that code does.
// Nice explicit casts like you usually use in Java.
// The result is of course again a double that is boxed into a Double object
Number d = a.doubleValue() + (double)b.intValue();
Use the following:
Number c = a.intValue() + b.intValue(); // Number is an object and not a primitive data type.
Or:
int a = 2;
int b = 3;
int c = 2 + 3;
I think there are 2 sides to your question.
Why is operator+ not supported on Number?
Because the Java language spec. does not specify this, and there is no operator overloading. There is also not a compile-time natural way to cast the Number to some fundamental type, and there is no natural add to define for some type of operations.
Why are basic arithmic operations not supported on Number?
(Copied from my comment:)
Not all subclasses can implement this in a way you would expect. Especially with the Atomic types it's hard to define a usefull contract for e.g. add.
Also, a method add would be trouble if you try to add a Long to a Short.
If you know the Type of one number but not the other it is possible to do something like
public Double add(Double value, Number increment) {
return value + Double.parseDouble(increment.toString());
}
But it can be messy, so be aware of potential loss of accuracy and NumberFormatExceptions
Number is an abstract class which you cannot make an instance of. Provided you have a correct instance of it, you can get number.longValue() or number.intValue() and add them.
First of all, you should be aware that Number is an abstract class. What happens here is that when you create your 2 and 3, they are interpreted as primitives and a subtype is created (I think an Integer) in that case. Because an Integer is a subtype of Number, you can assign the newly created Integer into a Number reference.
However, a number is just an abstraction. It could be integer, it could be floating point, etc., so the semantics of math operations would be ambiguous.
Number does not provide the classic map operations for two reasons:
First, member methods in Java cannot be operators. It's not C++. At best, they could provide an add()
Second, figuring out what type of operation to do when you have two inputs (e.g., a division of a float by an int) is quite tricky.
So instead, it is your responsibility to make the conversion back to the specific primitive type you are interested in it and apply the mathematical operators.
The best answer would be to make util with double dispatch drilling down to most known types (take a look at Smalltalk addtition implementation)
I am reading a currency from XML into Java.
String currency = "135.69";
When I convert this to BigDecimal I get:
System.out.println(new BigDecimal(135.69));
Output:
135.68999999999999772626324556767940521240234375.
Why is it that it outputs this many numbers? How can I avoid this? All I want is for it to output 135.69.
The BigDecimal(double) constructor can have unpredictable behaviors. It is preferable to use BigDecimal(String) or BigDecimal.valueOf(double).
System.out.println(new BigDecimal(135.69)); //135.68999999999999772626324556767940521240234375
System.out.println(new BigDecimal("135.69")); // 135.69
System.out.println(BigDecimal.valueOf(135.69)); // 135.69
The documentation for BigDecimal(double) explains in detail:
The results of this constructor can be somewhat unpredictable. One might assume that writing new BigDecimal(0.1) in Java creates a
BigDecimal which is exactly equal to 0.1 (an unscaled value of 1, with
a scale of 1), but it is actually equal to
0.1000000000000000055511151231257827021181583404541015625. This is because 0.1 cannot be represented exactly as a double (or, for that
matter, as a binary fraction of any finite length). Thus, the value
that is being passed in to the constructor is not exactly equal to
0.1, appearances notwithstanding.
The String constructor, on the other hand, is perfectly predictable: writing new BigDecimal("0.1") creates a BigDecimal which
is exactly equal to 0.1, as one would expect. Therefore, it is
generally recommended that the String constructor be used in
preference to this one.
When a double must be used as a source for a BigDecimal, note that this constructor provides an exact conversion; it does not give
the same result as converting the double to a String using the
Double.toString(double) method and then using the BigDecimal(String)
constructor. To get that result, use the static valueOf(double)
method.
String currency = "135.69";
System.out.println(new BigDecimal(currency));
//will print 135.69
You are storing 135.69 as String in currency. But instead of passing variable currency, you are again passing 135.69(double value) into new BigDecimal().
So you are seeing a lot of numbers in the output.
If you pass the currency variable, your output will be 135.69
May I add something. If you are using currency you should use Scale(2), and you should probably figure out a round method.
BigDecimal b = BigDecimal.valueOf(d);
import java.math.*;
public class Test {
public static void main(String[] args)
{
// Creating a Double Object
Double d = new Double("785.254");
/// Assigning the bigdecimal value of ln to b
BigDecimal b = BigDecimal.valueOf(d);
// Displaying BigDecimal value
System.out.println("The Converted BigDecimal value is: " + b);
}
}
Spring Framework provides an excellent utils class for achieving this.
Util class : NumberUtils
String to BigDecimal conversion -
NumberUtils.parseNumber("135.00", BigDecimal.class);
Hi Guys you cant convert directly string to bigdecimal
you need to first convert it into long after that u will convert big decimal
String currency = "135.69";
Long rate1=Long.valueOf((currency ));
System.out.println(BigDecimal.valueOf(rate1));
I'm trying to create a BigDecimal class that has always a fixed maximum fractions count.
But when printing that number, it is not cut to the fractions I defined in scale. Why?
class MyDecimal extends BigDecimal {
public MyDecimal(double val) {
super(val);
setScale(4, RoundingMode.HALF_UP);
}
}
Sysout(new MyDecimal(0.0001));
//0.000100000000000000008180305391403130954586231382563710212707519531254
BigDecimal is immutable, and should not be extended. setScale() does not modify the BigDecimal instance. It returns a copy of the BigDecimal instance with the scale modified (as every other "mutating" method of BigDecimal, since it's immutable). Calling it and ignoring the returned value is thus useless.
Instead of extending BigDecimal, create a factory method:
public static BigDecimal createWithScale4(double d) {
BigDecimal temp = new BigDecimal(d);
return temp.setScale(4);
}
The problem is that you are putting in your input as a double. This is from the javadoc:
The results of this constructor can be somewhat unpredictable. One
might assume that writing new BigDecimal(0.1) in Java creates a
BigDecimal which is exactly equal to 0.1 (an unscaled value of 1, with
a scale of 1), but it is actually equal to
0.1000000000000000055511151231257827021181583404541015625. This is because 0.1 cannot be represented exactly as a double (or, for that
matter, as a binary fraction of any finite length). Thus, the value
that is being passed in to the constructor is not exactly equal to
0.1, appearances notwithstanding
Since you are using a double, it is being stored as a floating-point number, and not as a precision number. It then converts that non-precision floating-point number to a precision BigDecimal, which then puts it out as a precise number. It works if the input is a String, however, since a String is just text, and converts the string directly to a BigDecimal. See this from here:
Creating a big decimal from a (scalar) double is simple:
bd = new BigDecimal(1.0);
To get a BigDecimal from a Double, get its
doubleValue() first.
However it is a good idea to use the string constructor:
bd = new BigDecimal("1.5");
If you don't, then you'll get the following,
bd = new BigDecimal(1.5);
bd.toString(); // => 0.1499999999999999944488848768742172978818416595458984375
So do it like this:
Sysout(new MyDecimal("0.0001"));
Also, as #JBNizet points out, you're extending an immutable object, a BigDecimal. You're ignoring the return value of setting the scale. This could be changed by using a method such as the one below:
public static BigDecimal createBigDecimal(String s) {
BigDecimal bigdeci = new BigDecimal(s);
return bigdeci.setScale(4);
}
The problem is that you're passing the argument as a double instead of as a string. Before the argument reaches the Big Decimal, it has already been converted into binary form to store as a double, which introduces a tiny error (it's equivalent to trying to write 1/3 as a decimal and getting 0.3333333333; it won't be quite right unless you have infinite precision).
Instead, try:
Sysout((new BigDecimal("0.0001")).setScale(4,RoundingMode.HALF_UP));
Sorry for the title name but this is probably a funny question. i need to have this like it is. I have an array of floats in the format [10.0, 20.0, 30.0, 40.0, 50.0] i need the array to be represented like [10.0f, 20.0f, 30.0f, 40.0f, 50.0f]. I have tried using array List to convert and add the notation and convert back.. but no matter what i try, i still get a float array that looks like a double. Any ideas Please?
even tried something like this:
ArrayList<String> valuelist = new ArrayList<String>();
for(int z = 0; z < mValues.length; z++){
valuelist.add(Float.toString(mValues[z]) + "f");
} //its fine here but later changes
Object[] objarray2 = valuelist.toArray();
String[] stringfloat = Arrays.copyOf(objarray2, objarray2.length, String[].class);
float[] myfloat = new float[stringfloat.length];
for(int j =0; j< myfloat.length; j++){
//myfloat[j] = Float.parseFloat(stringfloat[j]);
myfloat[j] = Float.valueOf(stringfloat[j]);
}
f is used to tell the compiler that treat this as float number. If you want your array in this format use an array of string and append f in each element
As per JLS:
A floating-point literal is of type float if it is suffixed with an ASCII letter F or f; otherwise its type is double and it can optionally be suffixed with an ASCII letter D or d (ยง4.2.3).
You have:
myfloat[j] = Float.valueOf(stringfloat[j]);
Here's Float.valueOf(String):
public static Float valueOf(String s) throws NumberFormatException
{
return new Float(FloatingDecimal.readJavaFormatString(s).floatValue())
}
As you can see, it returns a Float, which is created through Float(float) constructor, which is simply:
public Float(double value)
{
this.value = (float) value;
}
The readJavaFormatString(String) converts the String to a double, and .floatValue() converts the double, wrapped in a FloatingDecimal to a float, which is passed to the above constructor.
So, im short, you do have a float.
NB:
float num1 = XYZ;
float num2 = XYZf;
Despite the different notation, num1 and num2 compile to the same bytecode (where XYZ are some numbers, say 123); however, you cannot make an assignment of a number ending in an f to say an int. Additionally, if you try to put an int into a float, you do not need the f at the end, but if your number has any numbers to the right of the radix, you need to append the f so that it will compile with a possible loss of precision error.
Also, you really shouldn't be using float unless there's a good reason to do so, especially if you're planning to use == for comparison; instead, use double. float and double are essentially the same thing, except that double is 64-bits, whereas a float is 32-bits, so a double is more precise.
Keep the original array where members are float and just create a "String myToString()" method to print it like you want, with the +"f".
I mean, create a personalized method to print the array like you want it to appear.
I assume you just want the print out of the array of float to "appear" with a final f.
The representation in the machine of the number will not change with an f at the end or not.
The final f in the string is useful when parsing a number, so you the parser knows which kind of number it is, if you already do not tell it.
How to convert a long number in base 10 to base 9 without converting to string ?
FWIW, all values are actually in base 2 inside your machine (I bet you already knew that). It only shows up as base 10 because string conversion creates string representations in base 10 (e.g. when you print), because methods like parseLong assumes the input string is in base 10 and because the compiler expects all literals to be in base 10 when you actually write code. In other words, everything is in binary, the computer only converts stuff into and from base 10 for the convenience of us humans.
It follows that we should be easily able to change the output base to be something other than 10, and hence get string representations for the same value in base 9. In Java this is done by passing an optional extra base parameter into the Long.toString method.
long x=10;
System.out.println(Long.toString(x,9));
Long base10 = 10;
Long.valueOf(base10.toString(), 9);
What does "convert to base 9 without converting to string" actually mean?
Base-9, base-10, base-2 (binary), base-16 (hexadecimal), are just ways to represent numbers. The value itself does not depend on how you represent it. int x = 256 is exactly the same as int x = 0xff as far as the compiler is concerned.
If you don't want to "convert to string" (I read this as meaning you are not concerned with the representation of the value), then what do you want to do exactly?
You can't convert to base 9 without converting to string.
When you write
Long a = 123;
you're making the implicit assumption that it's in base 10. If you want to interpret that as a base 9 number that's fine, but there's no way Java (or any other language I know of) is suddenly going to see it that way and so 8+1 will return 9 and not 10. There's native support for base 2, 8, 16 and 10 but for any other base you'll have to treat it as a string. (And then, if you're sure you want this, convert it back to a long)
You have to apply the algorithm that converts number from one base to another by applying repeated modulo operations. Look here for a Java implementation. I report here the code found on that site. The variable M must contain the number to be converted, and N is the new base.
Caveat: for the snippet to work properly, N>=1 && N<=10 must be true. The extension with N>10 is left to the interested reader (you have to use letters instead of digits).
String Conversion(int M, int N) // return string, accept two integers
{
Stack stack = new Stack(); // create a stack
while (M >= N) // now the repetitive loop is clearly seen
{
stack.push(M mod N); // store a digit
M = M/N; // find new M
}
// now it's time to collect the digits together
String str = new String(""+M); // create a string with a single digit M
while (stack.NotEmpty())
str = str+stack.pop() // get from the stack next digit
return str;
}
If you LITERALLY can do anything but convert to string do the following:
public static long toBase(long num, int base) {
long result;
StringBuilder buffer = new StringBuilder();
buffer.append(Long.toString(num, base));
return Long.parseLong(buffer.toString());
}