Java: double rounding algorithm - java

I got curious about a rounding algorithm, because in CS we had to emulate an HP35 without using the Math library. We didn't include a rounding algorithm in our final build, but I wanted to do it anyway.
public class Round {
public static void main(String[] args) {
/*
* Rounds by using modulus subtraction
*/
double a = 1.123599;
// Should you port this to another method, you can take this as a parameter
int b = 5;
double accuracy = Math.pow(10, -b);
double remainder = a % accuracy;
if (remainder >= 5 * accuracy / 10) // Divide by ten is important because remainder is smaller than accuracy
a += accuracy;
a -= remainder;
/*
* Removes round off error done by modulus
*/
String string = Double.toString(a);
int index = string.indexOf('.') + b;
string = string.substring(0, index);
a = Double.parseDouble(string);
System.out.println(a);
}
}
Is this a good algorithm, or are there any better ones? I don't care about the ones defined in the Java API, I just wanted to know how it was done.
[EDIT]
Here's the code I came up with after looking over EJP's answer
public class Round {
public static void main(String[] args) {
double a = -1.1234599;
int b = 5;
boolean negative = a < 0;
if (negative) a = -a;
String string = Double.toString(a);
char array[] = string.toCharArray();
int index = string.indexOf('.') + b;
int i = index;
int value;
if (Character.getNumericValue(array[index +1]) >= 5) {
for (; i > 0; i--) {
value = Character.getNumericValue(array[i]);
if (value != -1) {
++value;
String temp = Integer.toString(value)
array[i] = temp.charAt(temp.length()-1);
if (value <= 9) break;
}
}
}
string = "";
for (int j=0; j < index + 1 ; j++) {
string += array[j];
}
a = Double.parseDouble(string);
if (negative) a =-a;
System.out.println(a);
}
}

Floating-point numbers don't have decimal places. They have binary places, and the two are not commensurable. Any attempt to modify a floating-point variable to have a specific number of decimal places is doomed to failure.
You have to do the rounding to a specified number of decimal places after conversion to a decimal radix.

There are a different ways to round numbers. The RoundingMode documentation for Java (introduced in 1.5) should give you a brief introduction to the different methods people use.
I know you said you don't have access to the Math functions, but the simplest rounding you can do is:
public static double round(double d)
{
return Math.floor(d + 0.5);
}
If you don't want to use any Math functions, you could try something like this:
public static double round(double d)
{
return (long)(d + 0.5);
}
Those two probably behave differently in some situations (negative numbers?).

Related

Mathematical Operations Without Using Java Math Class

I've been making my own class library in Java and I've run into a small annoyance. The library is centered around math. I started with the intention of not using the Java Math Class. Unfortunately, my lack of skill paired with my inability to find a resource online that tackles this problem has resulted in me falling back onto the Java Math Class. Is there a way I can do logarithms without using Math.log?
We could try to use a power series as per: https://math.stackexchange.com/a/61283
For example:
#Test
public void printMathCalculation() {
double libValue = Math.log(100);
double myValue = getLn(100);
System.out.println("Actual: \t" + libValue);
System.out.println("Approximate: \t" + myValue);
}
//Take double to an integer power
private double pow(double num, int power) {
double result = 1;
for(int i = 0; i < power; i++) {
result *= num;
}
return result;
}
//Get natural log
private double getLn(double num) {
int accuracy = 1000;
double sum = 0;
for(int n = 0; n < accuracy; n++) {
double num1 = (1.0/(2*n+1));
double num2 = (num-1)/(num+1);
sum += num1*pow(num2,2*n+1);
}
return 2 * sum;
}
The results I get are:
Actual: 4.605170185988092
Approximate: 4.605170185988078
You should use Math.log
Try this, using simple maths to calculate
public static int toLog2N(int num){
return num>1 ? 1 + toLog2N(num/2) : 0;
}
Its just an example, you should use Math class as it provides different methods like log(double a), log10(double a), log1p(double a). It will make your code more readable and easier to understand.
hope it helps!

power function to find the power where exponent is in decimal and less than 1

I was trying to create a program that finds the power of a real number . The problem is that exponent is in decimal and less than 1 but not negative.
suppose we have to find the power of
50.76
what i really tried was i wrote 0.76 as 76/100 and it would be 576/100
and after that i wrote
here is the code if you want to see what i did
public class Struct23 {
public static void main(String[] args) {
double x = 45;
int c=0;
StringBuffer y =new StringBuffer("0.23");
//checking whether the number is valid or not
for(int i =0;i<y.length();i++){
String subs = y.substring(i,i+1);
if(subs.equals(".")){
c=c+1;
}
}
if(c>1){
System.out.println("the input is wrong");
}
else{
String nep= y.delete(0, 2).toString();
double store = Double.parseDouble(nep);
int length = nep.length();
double rootnum = Math.pow(10, length);
double skit = power(x,store,rootnum);
System.out.println(skit);
}
}
static double power(double x,double store,double rootnum){
//to find the nth root of number
double number = Math.pow(x, 1/rootnum);
double power = Math.pow(number, store);
return power;
}
}
the answer would come but the main problem is that i cannot use pow function to do that
i can't also use exp() and log() functions.
i can only use
+
-
*
/
help me suggest your ideas .
thanks in advance
def newtons_sqrt(initial_guess, x, threshold=0.0001):
guess = initial_guess
new_guess = (guess+float(x)/guess)/2
while abs(guess-new_guess) > threshold :
guess=new_guess
new_guess = (guess+float(x)/guess)/2
return new_guess
def power(base, exp,threshold=0.00001):
if(exp >= 1): # first go fast!
temp = power(base, exp / 2);
return temp * temp
else: # now deal with the fractional part
low = 0
high = 1.0
sqr = newtons_sqrt(base/2,base)
acc = sqr
mid = high / 2
while(abs(mid - exp) > threshold):
sqr = newtons_sqrt(sqr/2.0,sqr)
if (mid <= exp):
low = mid
acc *= sqr
else:
high = mid
acc *= (1/sqr)
mid = (low + high) / 2;
return acc
print newtons_sqrt(1,8)
print 8**0.5
print power(5,0.76)
print 5**0.76
I reapropriated most of this answer from https://stackoverflow.com/a/7710097/541038
you could also expound on newtons_sqrt to give newtons_nth_root ... but then you have to figure out that 0.76 == 76/100 (which im sure isnt too hard really)
you can convert your number to complex form of it and then use de Moivre' formula to compute the nth root of your number using your legal oprations.

How to convert a String to a Float character by character using Java?

I was asked this on an interview a while back and couldn't figure it out. I wasn't allowed to cast the entire thing at once so my next idea was to just run through the string converting until the point but the guy interviewing me told me he wanted to do something like this:
1 = 1
12 = 1 * 10 + 2
123 = 12 * 10 + 3
1234 = 123 * 10 + 4
The input is convert "1234.567" to a float ie. 1234.567
I honestly have no idea how he meant to do it and I haven't been able to produce good enough code to show you guys all I had was the for cycling to parse each character:
for(int i = 0; i < str.length(); i++){
if(!str.charAt(i).equals(".")){
fp = Float.parseFloat("" + str.charAt(i));
Something like this (note: no error checking):
public float parseFloatFromString(final String input)
{
boolean seenDot = false;
float divisor = 1.0f;
char c;
float ret = 0.0f;
for (int i = 0; i < input.length(); i++) {
c = input.charAt(i);
if (c == '.') {
seenDot = true;
continue;
}
ret *= 10.0f;
ret += (float) (c - '0');
if (seenDot)
divisor *= 10.0f;
}
ret /= divisor;
return ret;
}
Of course, you are limited by what a float can represent as decimal numbers -- ultimately, not much. Especially in this case where you multiply/add all the time, and let's not talk about the final division (if the divisor is not 1).
Interesting note about the above: in fact, it appears that this may yield different results on different platforms... Modern JVMs on modern platforms may use an internal, higher precision intermediate representation for floating points. If you want the same result everywhere, you have to add the modifier strictfp to the method declaration:
public strictfp float parseFloatFromString(final String input)
More details here.
This isn't especially elegant, but does work.
String s = "1234.567";
Float fp = 0f;
Float fpd = 0f;
int i =0;
while(s.charAt(i) != '.') {
fp = (fp * 10) + Float.parseFloat(s.substring(i, (i+1)));
i++;
}
int d = s.indexOf('.');
for(i = s.length()- 1; i > d; i--) {
fpd = (fpd * 0.1f) + (Float.parseFloat(s.substring(i, (i+1))) * 0.1f);
}
fp += fpd;
System.out.println(fp);
I can't understand what's your meaning? Did you meaning that convert the integer like '123456' to '12345 * 10 + 6', if you want to do this, just use the 'substring' method to do this.
You would want to trim the source string and then create the number a digit at a time, while counting how many digits occur after an optional decimal point (so you can scale the resulting number).
public class MakeFloat {
private static MakeFloat me;
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
me = new MakeFloat();
String source = " 1234.567";
float result = me.start(source);
System.out.println(" " + source + "=" + result);
}
private float start(String string) {
final String digits = "0123456789";
final float[] values = {0,1,2,3,4,5,6,7,8,9};
float ten = 10;
float result = 0;
float scale = 1;
boolean isAfterDecimal = false;
String stepThrough = string.trim();
for (int i = 0; i < stepThrough.length(); i++) {
// see if we have a digit or a decimal point
String digit = stepThrough.substring(i, i + 1);
int loc = digits.indexOf(digit);
if (loc > -1) {
result = ten * result + values[loc];
if (isAfterDecimal) {
scale = scale * ten;
}
} else if (".".equals(digit)) {
if (isAfterDecimal) {
// handle error
} else {
isAfterDecimal = true;
}
} else {
// handle bad character
}
}
return result / scale;
}
}
To convert a string to a float, I personally use this:
Float.parseFloat("1234.567");
For what the guy wanted, this would be my way of doing it:
String num = "1234.567";
int dotLocation = num.indexOf(".");
int wholeNum = Integer.parseInt(num.substring(0, dotLocation));
String answer = (wholeNum / 10) + " * 10 + " + (wholeNum % 10);
Locate the position of the "." in the string, then extract the whole number by taking a substring of the original string. This would give us 1234.
We now then need to format it such that we get 1234 = 123 * 10 + 4.
Mathematically, when you divide 1234 by 10, the quotient would be 123 and the remainder would be 4. This would give you the answer the guy wanted.
package com.nanofaroque.float2String;
public class Float2String {
public static void main(String[] args) {
String input="1234.56";
String str=".";
float result=0;
int j=3;//this is used for multiply by 10^j
for(int i=0;i<input.length();i++){
if (input.charAt(i)!=str.charAt(0)){
char m=input.charAt(i);//Convert String to Character
float x=(float) input.charAt(i);//Getting the ASCI value
x=x-48;//Now x converted to the real float value
float y=(float) (x* (Math.pow(10, j)));//Multiplication Operation for conversion
result=result+y;
j=j-1;
}
else{
System.out.println("Welcome to my World");// to make the loop work..You can change it if you want
}
}
System.out.println("Result after the conversion:"+result);
}
}

What is the best way to separate double into two parts "integer & fraction" in java

I have tried to separate 5.6 (for example) by the following method:
private static double[] method(double d)
{
int integerPart = 0;
double fractionPart = 0.0;
integerPart = (int) d;
fractionPart = d - integerPart;
return new double[]{integerPart, fractionPart};
}
But what I got is:
[0] = 5.0
[1] = 0.5999999999999996
Do you have any suggestion about doing this without converting the number to string?
Use BigDecimal to do that same calculation. (using doubles has precision problems because of its representation).
Construct it with new BigDecimal(String.valueOf(yourDouble)) (this is still going through string, but the parts are not separated via string manipulation)
use bd.subtract(new BigDecimal(bd.intValue()) to determine the fraction
Here is another solution based on BigDecimal (that does not go through a String).
private static double[] method(double d) {
BigDecimal bd = new BigDecimal(d);
return new double[] { bd.intValue(),
bd.remainder(BigDecimal.ONE).doubleValue() };
}
As you'll note, you still won't get just 0.6 as output for the fractional part. (You can't even store 0.6 in a double!) This is due to the fact that the mathematical, real number, 5.6 is actually not represented by a double exactly as 5.6 but as 5.599999...
You could also do
private static double[] method(double d) {
BigDecimal bd = BigDecimal.valueOf(d);
return new double[] { bd.intValue(),
bd.remainder(BigDecimal.ONE).doubleValue() };
}
which actually does yield [5.0, 0.6].
The BigDecimal.valueOf is in most JDK's (internally) implemented through a call to Double.toString however. But at least the string-related stuff doesn't clutter your code :-)
Good follow-up question in comment:
If it is represented as 5.599999999..., then why Double.toString(5.6) gives exactly "5.6"
The Double.toString method is actually very sophisticated. From the documentation of Double.toString:
[...]
How many digits must be printed for the fractional part of m or a? There must be at least one digit to represent the fractional part, and beyond that as many, but only as many, more digits as are needed to uniquely distinguish the argument value from adjacent values of type double. That is, suppose that x is the exact mathematical value represented by the decimal representation produced by this method for a finite nonzero argument d. Then d must be the double value nearest to x; or if two double values are equally close to x, then d must be one of them and the least significant bit of the significand of d must be 0.
[...]
The code for getting the characters "5.6" boils down to FloatingDecimal.getChars:
private int getChars(char[] result) {
assert nDigits <= 19 : nDigits; // generous bound on size of nDigits
int i = 0;
if (isNegative) { result[0] = '-'; i = 1; }
if (isExceptional) {
System.arraycopy(digits, 0, result, i, nDigits);
i += nDigits;
} else {
if (decExponent > 0 && decExponent < 8) {
// print digits.digits.
int charLength = Math.min(nDigits, decExponent);
System.arraycopy(digits, 0, result, i, charLength);
i += charLength;
if (charLength < decExponent) {
charLength = decExponent-charLength;
System.arraycopy(zero, 0, result, i, charLength);
i += charLength;
result[i++] = '.';
result[i++] = '0';
} else {
result[i++] = '.';
if (charLength < nDigits) {
int t = nDigits - charLength;
System.arraycopy(digits, charLength, result, i, t);
i += t;
} else {
result[i++] = '0';
}
}
} else if (decExponent <=0 && decExponent > -3) {
result[i++] = '0';
result[i++] = '.';
if (decExponent != 0) {
System.arraycopy(zero, 0, result, i, -decExponent);
i -= decExponent;
}
System.arraycopy(digits, 0, result, i, nDigits);
i += nDigits;
} else {
result[i++] = digits[0];
result[i++] = '.';
if (nDigits > 1) {
System.arraycopy(digits, 1, result, i, nDigits-1);
i += nDigits-1;
} else {
result[i++] = '0';
}
result[i++] = 'E';
int e;
if (decExponent <= 0) {
result[i++] = '-';
e = -decExponent+1;
} else {
e = decExponent-1;
}
// decExponent has 1, 2, or 3, digits
if (e <= 9) {
result[i++] = (char)(e+'0');
} else if (e <= 99) {
result[i++] = (char)(e/10 +'0');
result[i++] = (char)(e%10 + '0');
} else {
result[i++] = (char)(e/100+'0');
e %= 100;
result[i++] = (char)(e/10+'0');
result[i++] = (char)(e%10 + '0');
}
}
}
return i;
}
To see what is going on, take a look at the binary representations of the numbers:
double d = 5.6;
System.err.printf("%016x%n", Double.doubleToLongBits(d));
double[] parts = method(d);
System.err.printf("%016x %016x%n",
Double.doubleToLongBits(parts[0]),
Double.doubleToLongBits(parts[1]));
output:
4016666666666666
4014000000000000 3fe3333333333330
5.6 is 1.4 * 22, but 0.6 is 1.2 * 2-1. Because it has a lower exponent, normalization causes the mantissa to be shifted three bits to the left. The fact that the recurring terms (..66666..) were originally an approximation of the fraction 7/5 has been forgotten, and the missing bits are replaced with zeros.
Given the original double value as input to your method, there is no way to avoid this. To preserve the exact value you would need to use a format that represents the desired value exactly, e.g. Fraction from Apache commons-math. (For this specific example with d=5.6 a BigDecimal would also be able to represent it exactly, but there are other numbers it cannot represent exactly, e.g. 4/3)
poor-man solution (using String)
static double[] sp(double d) {
String str = String.format(Locale.US, "%f", d);
int i = str.indexOf('.');
return new double[] {
Double.parseDouble(str.substring(0, i)),
Double.parseDouble(str.substring(i))
};
}
(Locale so we really get a decimal point)
String doubleAsString = Double.toString(123.456);
String beforeDecimal=doubleAsString.substring(0,doubleAsString.indexOf(".")); //123
String afterDecimal=doubleAsString.substring(doubleAsString.indexOf(".")+1); //456

Find the max of 3 numbers in Java with different data types

Say I have the following three constants:
final static int MY_INT1 = 25;
final static int MY_INT2 = -10;
final static double MY_DOUBLE1 = 15.5;
I want to take the three of them and use Math.max() to find the max of the three but if I pass in more then two values then it gives me an error. For instance:
// this gives me an error
double maxOfNums = Math.max(MY_INT1, MY_INT2, MY_DOUBLE2);
Please let me know what I'm doing wrong.
Math.max only takes two arguments. If you want the maximum of three, use Math.max(MY_INT1, Math.max(MY_INT2, MY_DOUBLE2)).
you can use this:
Collections.max(Arrays.asList(1,2,3,4));
or create a function
public static int max(Integer... vals) {
return Collections.max(Arrays.asList(vals));
}
If possible, use NumberUtils in Apache Commons Lang - plenty of great utilities there.
https://commons.apache.org/proper/commons-lang/javadocs/api-3.1/org/apache/commons/lang3/math/NumberUtils.html#max(int[])
NumberUtils.max(int[])
Math.max only takes two arguments, no more and no less.
Another different solution to the already posted answers would be using DoubleStream.of:
double max = DoubleStream.of(firstValue, secondValue, thirdValue)
.max()
.getAsDouble();
Without using third party libraries, calling the same method more than once or creating an array, you can find the maximum of an arbitrary number of doubles like so
public static double max(double... n) {
int i = 0;
double max = n[i];
while (++i < n.length)
if (n[i] > max)
max = n[i];
return max;
}
In your example, max could be used like this
final static int MY_INT1 = 25;
final static int MY_INT2 = -10;
final static double MY_DOUBLE1 = 15.5;
public static void main(String[] args) {
double maxOfNums = max(MY_INT1, MY_INT2, MY_DOUBLE1);
}
Java 8 way. Works for multiple parameters:
Stream.of(first, second, third).max(Integer::compareTo).get()
I have a very simple idea:
int smallest = Math.min(a, Math.min(b, Math.min(c, d)));
Of course, if you have 1000 numbers, it's unusable, but if you have 3 or 4 numbers, its easy and fast.
Regards,
Norbert
Like mentioned before, Math.max() only takes two arguments. It's not exactly compatible with your current syntax but you could try Collections.max().
If you don't like that you can always create your own method for it...
public class test {
final static int MY_INT1 = 25;
final static int MY_INT2 = -10;
final static double MY_DOUBLE1 = 15.5;
public static void main(String args[]) {
double maxOfNums = multiMax(MY_INT1, MY_INT2, MY_DOUBLE1);
}
public static Object multiMax(Object... values) {
Object returnValue = null;
for (Object value : values)
returnValue = (returnValue != null) ? ((((value instanceof Integer) ? (Integer) value
: (value instanceof Double) ? (Double) value
: (Float) value) > ((returnValue instanceof Integer) ? (Integer) returnValue
: (returnValue instanceof Double) ? (Double) returnValue
: (Float) returnValue)) ? value : returnValue)
: value;
return returnValue;
}
}
This will take any number of mixed numeric arguments (Integer, Double and Float) but the return value is an Object so you would have to cast it to Integer, Double or Float.
It might also be throwing an error since there is no such thing as "MY_DOUBLE2".
int first = 3;
int mid = 4;
int last = 6;
//checks for the largest number using the Math.max(a,b) method
//for the second argument (b) you just use the same method to check which //value is greater between the second and the third
int largest = Math.max(first, Math.max(last, mid));
You can do like this:
public static void main(String[] args) {
int x=2 , y=7, z=14;
int max1= Math.max(x,y);
System.out.println("Max value is: "+ Math.max(max1, z));
}
if you want to do a simple, it will be like this
// Fig. 6.3: MaximumFinder.java
// Programmer-declared method maximum with three double parameters.
import java.util.Scanner;
public class MaximumFinder
{
// obtain three floating-point values and locate the maximum value
public static void main(String[] args)
{
// create Scanner for input from command window
Scanner input = new Scanner(System.in);
// prompt for and input three floating-point values
System.out.print(
"Enter three floating-point values separated by spaces: ");
double number1 = input.nextDouble(); // read first double
double number2 = input.nextDouble(); // read second double
double number3 = input.nextDouble(); // read third double
// determine the maximum value
double result = maximum(number1, number2, number3);
// display maximum value
System.out.println("Maximum is: " + result);
}
// returns the maximum of its three double parameters
public static double maximum(double x, double y, double z)
{
double maximumValue = x; // assume x is the largest to start
// determine whether y is greater than maximumValue
if (y > maximumValue)
maximumValue = y;
// determine whether z is greater than maximumValue
if (z > maximumValue)
maximumValue = z;
return maximumValue;
}
} // end class MaximumFinder
and the output will be something like this
Enter three floating-point values separated by spaces: 9.35 2.74 5.1
Maximum is: 9.35
References Java™ How To Program (Early Objects), Tenth Edition
Simple way without methods
int x = 1, y = 2, z = 3;
int biggest = x;
if (y > biggest) {
biggest = y;
}
if (z > biggest) {
biggest = z;
}
System.out.println(biggest);
// System.out.println(Math.max(Math.max(x,y),z));

Categories

Resources