I want to do an operation like this : if the given float numbers are like 1.0 , 2.0 , 3.0 , I want to save them to database as integer (1,2,3 ), if they are like 1.1 , 2.1 , ,3.44 , I save them as float. what's the best solution for this problem using java ? The corresponding field in database is type of varchar.
Just try int i = (int) f;.
EDIT : I see the point in the question. This code might work :
int i = (int) f;
String valToStore = (i == f) ? String.valueOf(i) : String.valueOf(f);
String result = "0";
if (floatVar == Math.floor(floatVar)) {
result = Integer.toString((int) floatVar);
} else {
result = Float.toString(floatVar);
}
The if-clause checks whether the number is a whole number - i.e. if it is equal to the result of rounding it down to the closest whole value.
But this is very odd requirement indeed, and perhaps you should reconsider the need for such a thing.
Seems like you want to save Floats with no trailing numbers as Integers, while saving those with significant trailing numbers as Floats. I would rather just save it all as Float to the DB, but it's your question so here's my answer:
/**
* Method to determine if trailing numbers are significant or not. Significant
* here means larger than 0
*
* #param fFloat
* #return
*/
public static boolean isTrailingSignificant(Float fFloat)
{
int iConvertedFloat = fFloat.intValue();// this drops trailing numbers
// checks if difference is 0
return ((fFloat - iConvertedFloat) > 0);
}
This is how you would use this method:
Number oNumToSave = null;
if (isTrailingSignificant(fFloat))
{
// save float value as is
oNumToSave = fFloat;
}
else
{
// save as int
oNumToSave = fFloat.intValue();// drops trailing numbers
}
After that, you can do the database operation using the variable oNumToSave.
Not sure this is the best solution, but you can try to write a method like this :
String convertToString(Float f) {
if (f.toString().endsWith(".0"))
return f.intValue().toString();
else
return f.toString();
}
Kotlin:
val mAmount = 3.0
val intAmount = mAmount.toInt()
val amountToDisplay = if (intAmount.compareTo(mAmount) == 0) intAmount.toString() else java.lang.String.valueOf(mAmount)
Related
I'm currently developing some functionality that needs to either subtract or add time to a Calendar class instance. The time I need to add/sub is in a properties file and could be any of these formats:
30,sec
90,sec
1.5,min
2,day
2.333,day
Let's assume addition for simplicity. I would read those values in a String array:
String[] propertyValues = "30,sec".split(",");
I would read the second value in that comma-separated pair, and map that to the relevant int in the Calendar class (so for example, "sec" becomes Calendar.SECOND, "min" becomes Calendar.MINUTE):
int calendarMajorModifier = mapToCalendarClassIntValues(propertyValues[1]);
To then do the actual operation I would do it as simple as:
cal.add(calendarMajorModifier, Integer.parseInt(propertyValues[0]));
This works and it's not overly complicated. The issue is now floating values (so 2.333,day for eaxmple) - how would you deal with it?
String[] propertyValues = "2.333,day".split(",");
As you can imagine the code becomes quite hairy (I haven't actually written it yet, so please ignore syntax mistakes)
float timeComponent = Float.parseFloat(propertyValues[0]);
if (calendarMajorModifier == Calendar.DATE) {
int dayValue = Integer.parseFloat(timeComponent);
cal.add(calendarMajorModifier, dayValue);
timeComponent = (timeComponent - dayValue) * 24; //Need to convert a fraction of a day to hours
if (timeComponent != 0) {
calendarMajorModifier = Calendar.HOUR;
}
}
if (calendarMajorModifier == Calendar.HOUR) {
int hourValue = Integer.parseFloat(timeComponent);
cal.add(calendarMajorModifier, hourValue);
timeComponent = (timeComponent - hourValue) * 60; //Need to convert a fraction of an hour to minutes
if (timeComponent != 0) {
calendarMajorModifier = Calendar.MINUTE;
}
}
... etc
Granted, I can see how there may be a refactoring opportunity, but still seems like a very brute-forceish solution.
I am using the Calendar class to do the operations on but could technically be any class. As long as I can convert between them (i.e. by getting the long value and using that), as the function needs to return a Calendar class. Ideally the class also has to be Java native to avoid third party licensing issues :).
Side note: I suggested changing the format to something like yy:MM:ww:dd:hh:mm:ss to avoid floating values but that didn't pan out. I also suggested something like 2,day,5,hour, but again, ideally needs to be format above.
I'd transform the value into the smallest unit and add that:
float timeComponent = Float.parseFloat(propertyValues[0]);
int unitFactor = mapUnitToFactor(propertyValues[1]);
cal.add(Calendar.SECOND, (int)(timeComponent * unitFactor));
and mapUnitToFactor would be something like:
int mapUnitToFactor(String unit)
{
if ("sec".equals(unit))
return 1;
if ("min".equals(unit))
return 60;
if ("hour".equals(unit))
return 3600;
if ("day".equals(unit))
return 24*3600;
throw new InvalidParameterException("Unknown unit: " + unit);
}
So for example 2.333 days would be turned into 201571 seconds.
I want to do the average of 9 textfields and also the sum of them and place them in 2 other textfields by using a button, currently this code doesnt displays anything in the other textfiels. If i put anything, for example "A" instead of "%.Of" it would display the "A" in the textfield but not the average or the sum. Please i need help with a code that would work, dont mind if i need to change a lot.
This is what im working with:
private void jButton_RankingActionPerformed(java.awt.event.ActionEvent evt) {
double R[] = new double [14];
R[0] = Double.parseDouble(jTextField_Math.getText());
R[1]= Double.parseDouble(jTextField_English.getText());
R[2] = Double.parseDouble(jTextField_Spanish.getText());
R[3] = Double.parseDouble(jTextField_Biology.getText());
R[4] = Double.parseDouble(jTextField_Physics.getText());
R[5] = Double.parseDouble(jTextField_Chemestry.getText());
R[6] = Double.parseDouble(jTextField_PE.getText());
R[7] = Double.parseDouble(jTextField_Humanities.getText());
R[8] = Double.parseDouble(jTextField_Technology.getText());
R[9] = (R[0]+R[1]+R[2]+R[3]+R[4]+R[5]+R[6]+R[7]+R[8])/ 9;
R[10] = R[0]+R[1]+R[2]+R[3]+R[4]+R[5]+R[6]+R[7]+R[8];
String Average = String.format("%.Of",R[9]);
jTextField_Average.setText(Average);
String TotalScore = String.format("%.Of",R[10]);
jTextField_TotalScore.setText(TotalScore);
if(R[10]>=50)
{
jTextField_Ranking.setText("Superior");
}
else if (R[10]>=41){
jTextField_Ranking.setText("Alto");
}
else if (R[10]>=34){
jTextField_Ranking.setText("Basico");
}
else if (R[10]<=33){
jTextField_Ranking.setText("Bajo");
Since you mentioned that an A would print, it follows that jButton_RankingActionPerformed is being called. The issue you have is the format string you are using to print the total and average. You have mistakenly chosen the capital letter O rather than the number zero.
Replace this (which contains a capital letter O):
String.format("%.Of",R[9]);
With
1) No decimal will be printed: i.e. 50.2 would be 50
String.format("%.0f",R[9]);
2) Or perhaps you want to see one decimal place like 50.2
String.format("%.1f",R[9]);
Also a very small optimization is:
R[9] = (R[0]+R[1]+R[2]+R[3]+R[4]+R[5]+R[6]+R[7]+R[8])/ 9;
R[10] = R[0]+R[1]+R[2]+R[3]+R[4]+R[5]+R[6]+R[7]+R[8];
Could be replaced with:
R[10] = R[0]+R[1]+R[2]+R[3]+R[4]+R[5]+R[6]+R[7]+R[8];
R[9] = R[10] / 9;
or use a loop to calculate R[10]. (to add R[0] to R[8])
Using the share quote I need to find the range with the following input parameters:
price step : minimal price movement possible. Step = 0.01 mean that quotes can be 100.01, 100.1, but not 100.015. Can be > 1 for 'big' shares.
number of steps in range. Steps = 10 mean I need interval with 10 minimal price movements. Like [100.1 ; 100.2) Interval needs to be adjusted to minimal movement, so no [100.015; 100.15) intervals possible.
Input quote any double (6 digits after . is enough), may or may not obey price step rule (for example, direct value from stock market obeys, but average value is not). Obviously, quote should be in interval. I tried different approaches, but all of them fails.
Range is rather trivial:
public class Range<T extends Comparable> {
private T from = null;
private T to = null;
public Range(T from, T to) {
this.from = from;
this.to = to;
}
public T getFrom() {
return from;
}
public T getTo() {
return to;
}
#SuppressWarnings("unchecked")
public boolean contains(T value) {
return from.compareTo(value) <= 0 && to.compareTo(value) > 0;
}
#Override
public String toString() {
return "Range{" +
"from=" + from +
", to=" + to +
'}';
}
}
protected static Range<Double> getRangeFromPrice(double pips, int step, double price) {
BigDecimal modifier = new BigDecimal(pips * step).setScale(6, BigDecimal.ROUND_HALF_DOWN);
BigDecimal begin = new BigDecimal(price).divide(modifier, 0, BigDecimal.ROUND_HALF_DOWN).multiply(modifier);
return new Range<>(begin.doubleValue(), begin.add(modifier).doubleValue());
}
This function works most of the time, for example for pips = 0.01 and step = 10
price = 132 Range{from=132.0, to=132.1} OK
price = 132.01 Range{from=132.0, to=132.1} OK
price = 132.1 Range{from=132.1, to=132.2} OK
price = 132.15 Range{from=132.2, to=132.3} <- ERROR, price not in interval
I tried different rounding strategies, but all of them fails (in one example or another). Now I totally run out of ideas. How can I choose rounding strategy automatically?
Consider:
Decimal STEP = 0.1; // floating-point 0.1 is always imprecise.
Decimal shifted = price / step; // make steps integral.
Decimal left = trunc(price) * step; // always ≤ price.
Decimal right = trunc(price + 1) * step; // always > left.
return Range(left, right);
protected static Range<Double> getRangeFromPrice(double step, int count, double price) {
BigDecimal modifier = new BigDecimal(count * step).setScale(Common.PRICE_RESOLUTION, BigDecimal.ROUND_HALF_UP);
BigDecimal div = new BigDecimal(price).divide(modifier, Common.PRICE_RESOLUTION, BigDecimal.ROUND_HALF_EVEN).setScale(0, BigDecimal.ROUND_FLOOR);
BigDecimal begin = div.multiply(modifier);
Range<Double> ret = new Range<>(begin.doubleValue(), begin.add(modifier).doubleValue());
assert ret.contains(price);
return ret;
}
I solved original issue with the following code. Price shouldn't be really double, I use number(19,6) in database, however in application I use double as BigDecimal is rather slow.
If you want to use double, extra rounding is required.
This code pass my unit tests.
Before I get into detail, YES this is a HOMEWORK ASSIGNMENT. NO I DON'T WANT ANSWERS, JUST TIPS and/or Suggestions to try this or that.
The problem introduces with this:
Create a class, ExactNumber, that uses two long properties named left
and right (representing the portion of the number that is to the left
and right of the decimal point respectively). For example, 3.75 would
be represented by new ExactNumber(3, 7500000000000000L). Note the L on
the end which tells Java the large number is a long. This translates
to: 3 + 7500000000000000/10000000000000000 = 3.75
Here is my code:
public class ExactNumber {
private long left;
private long right;
public ExactNumber(long left, long right) {
this.left = left;
this.right = right;
}
public String toString() {
return String.valueOf(doubleValue());
}
public double doubleValue() {
return ((double) left + (double) (right/ 100000000000000L) / 100);
}
public int compareTo (ExactNumber exactNumber) {
if(exactNumber.left < left) {
return 1;
}
else if (exactNumber.left == left) {
if (exactNumber.right < right) {
return 1;
}
else if (exactNumber.right == right) {
return 0;
}
else {
return -1;
}
}
else {
return -1;
}
}
public boolean equal(ExactNumber thisobject) {
if (thisobject instanceof ExactNumber) {
if (thisobject.doubleValue() == this.doubleValue()) {
return true;
}
else {
return false;
}
}
else {
return false;
}
}
public double add(ExactNumber exactNumber) {;
return ((left+exactNumber.left) + (double)((right+exactNumber.right)*1E-16));
}
}
My problem are the tests coming up as an error when the expected value is equal to the actual value. Here are the test cases (NOTE: there are more test cases, but they pass the JUnit test):
public class TestExactNumber extends TestCase {
ExactNumber threesevenfive = new ExactNumber(3, 7500000000000000L);
ExactNumber threesevenfive_andalittlebit = new ExactNumber(3, 7500000000000001L);
ExactNumber threesevenfive_dupe = new ExactNumber(3, 7500000000000000L);
ExactNumber ten = new ExactNumber(10, 0);
ExactNumber thirteensevenfive = new ExactNumber(13, 7500000000000000L);
ExactNumber sevenfifty = new ExactNumber(7, 5000000000000000L);
public void test_equals() {
assertFalse(threesevenfive.equals(threesevenfive_andalittlebit));
assertEquals(threesevenfive, threesevenfive_dupe);
}
public void test_add() {
assertEquals(threesevenfive.add(ten), thirteensevenfive);
assertEquals(threesevenfive.add(threesevenfive), sevenfifty);
The assertEquals above failed in the JUnit test, but says like (for an example) expected = 13.75 and actual = 13.75.
Any tips or hints at what I need to do with my code is greatly appreciated. And thank you in advanced.
NOTES:
According to my instructor, I should not be using the doubleValue method to implement my equals method. I know that I do have it in my code, but that was prior to the tip the instructor gave me and I am just unsure about how to change it.
I am using eclipse for java to code this.
Your equal Method is never used. The Java Method used by assertEquals() is called equalS (and you have to override the equals() method derived from Object).
Therefore, the assertion will use equals inherited from Object, which will compare the actual instances rather than using YOUR equal method which will compare the objet values. And since they are two different INSTANCES, they are not equal.
Finally, the two instances will be plotted with toString() resulting in expected = 13.75 and actual = 13.75. (Because your toString() returns only the values, ignoring the difference between instances)
Your Instructors Response:
A Long in Java is a 64 bit long number. Double in Java is implemented with the IEEE754 Standard, which only leaves 52 bit for the mantissa. Meaning: Any conversion of a Long Number to a double, where the Long Number has set bits on bit 53 to 63 - will cause the exponent to be shifted in a way, that you loose precision arround the LSBs - resulting in an unprecice Double Value.
Therefore comparing the double values to determine equality is not sufficent for your desired Design of a "Exact Number".
Example:
Long bigLong = 1L<<51; //picked 51: 52 and 53 already causing rounding issues.
Long long1 = bigLong + 1L;
Long long2 = bigLong + 2L;
System.out.println(long1+" -> " + long1.doubleValue());
System.out.println(long2+" -> " + long2.doubleValue());
//false, enough precision to preserve bit "0" and "1".
System.out.println(long1.doubleValue()==long2.doubleValue());
Output:
2251799813685262 -> 2.251799813685262E15
2251799813685263 -> 2.251799813685263E15
false
When setting bit 54:
Long bigLong = 1L<<54;
Long long1 = bigLong + 1L;
Long long2 = bigLong + 2L;
System.out.println(long1+" -> " + long1.doubleValue());
System.out.println(long2+" -> " + long2.doubleValue());
System.out.println(long1.doubleValue()==long2.doubleValue());
Output:
18014398509481985 -> 1.8014398509481984E16
18014398509481986 -> 1.8014398509481984E16
true
Note the Exponent beeing increased from 15 to 16, which will cut off the difference of "1" between both longs.
To solve this, you can compare left1 to left2 and right1 to right2 without converting it to a double.
Your equal method should ideally test every necessary value in your class. In this case, it should be checking to see if your left and right values are the same between the two objects. If they are the same, then you can consider the objects to be equal.
In your case, you should probably put a debug point in your equals method to see why the function is returning back a false.
Try using Eclipse's built in functionality to create equals and hashcode methods for you. You can create that by going to Source->Generate hashCode() and equals(). The methods will be very different from what you have created.
Another thing, in your AssertEquals method, make sure both the values passed in are of the same type. In your case, you're checking a Double with an ExactNumber object. They will definitely not be the same. You need to either
Change your Add method to return a ExactNumber object
Have a method in your ExactNumber class called getDouble() and use that as the second parameter instead.
Hope this helps.
I am trying to display numbers in a string dynamically, so if the number has decimal's display them but if not don"t show the .0
example: display 5.5 as 5.5 and 5.0 as 5
This is what I have so far: (answer is a double)
double temp = answer;
long temp2 = (long) temp;
if (temp == temp2) {
output = String.valueOf(temp2);
System.out.println(output);
this work's fine up to about 1e18 then will error out because of the maximum size of a Long.
So how would I achieve this on bigger numbers like 5.43e86
Use DecimalFormat
double answer = 5.0;
DecimalFormat df = new DecimalFormat("###.#");
System.out.println(df.format(answer));
The DecimalFormat suggestions are the easiest way to handle this. If they aren't sufficient, here's another idea.
If you're starting to hit the maximum values that can be represented by primitives in Java, then you may need to move to BigInteger and BigDecimal.
Try playing around with the BigDecimal.toBigInteger() method coupled with the toString() methods on BigDecimal and BigInteger.
It's not good solution
if you use new DecimalFormat("0.#") you are missing data, for example
PI = 3.14, but after parse you ae geting 3.1
Another solution to use eval%1 ? (int)d : d
this time couse max integer limit , again missing data
my solution is working, but it's not good idea
res = removeLastChars(eval,".0");
private String removeLastChars(double eval, String text){
String res = String.valueOf(eval);
int length = text.length();
if (res.length() > length){
res = res.substring((res.length() - length), res.length()).equals(text)
? res.substring(0, (res.length() - length)) : res;
}
return res;
}
Look at
http://download.oracle.com/javase/6/docs/api/java/text/DecimalFormat.html
you would want just DecimalFormat("0.0")