Can you replicate the Floor function found in Excel in Java? - java

I have searched the internet but have not found any solutions for my question.
I would like to be able to use the same/replicate the type of FLOOR function found in Excel in Java. In particular I would like to be able to provide a value (double or preferably BigDecimal) and round down to the nearest multiple of a significance I provide.
Examples 1:
Value = 24,519.30235
Significance = 0.01
Returned Value = 24,519.30
Example 2:
Value = 76.81485697
Significance = 1
Returned Value = 76
Example 3:
Value = 12,457,854
Significance = 100
Returned Value = 12,457,800
I am pretty new to java and was wondering if someone knew if an API already includes the function or if they would be kind enough to give me a solution to the above. I am aware of BigDecimal but I might have missed the correct function.
Many thanks

Yes you can.
Lets say given numbers are
76.21445
and
0.01
what you can do is multiply 76.21445 by 100 (or divide per 0.01)
round the result to nearest or lower integer (depending which one you want)
and than multiply it by the number again.
Note that it may not exactly print what you want if you will not go for the numbers with decimal precision. (The problem of numbers which in the binary format are not finite in extansion). Also in Math you have the round function taking doing pretty much what you want.
http://docs.oracle.com/javase/7/docs/api/java/lang/Math.html you use it like this
round(200.3456, 2);
one Example Code could be
public static void main(String[] args) {
BigDecimal value = new BigDecimal("2.0");
BigDecimal significance = new BigDecimal("0.5");
for (int i = 1; i <= 10; i++) {
System.out.println(value + " --> " + floor(value, significance));
value = value.add(new BigDecimal("0.1"));
}
}
private static double floor(BigDecimal value, BigDecimal significance) {
double result = 0;
if (value != null) {
result = value.divide(significance).doubleValue();
result = Math.floor(result) * significance.doubleValue();
}
return result;
}

To round a BigDecimal, you can use setScale(). In your case, you want RoundingMode.FLOOR.
Now you need to determine the number of digits from the "significance". Use Math.log10(significance) for that. You'll probably have to round the result up.
If the result is negative, then you have a significance < 1. In this case, use setScale(-result, RoundingMode.FLOOR) to round to N digits.
If it's > 1, then use this code:
value
.divide(significance)
.setScale(0, RoundingMode.FLOOR)
.multiply(significance);
i.e. 1024 and 100 gives 10.24 -> 10 -> 1000.

Related

Java - Numbers aren't subtracting correctly? [duplicate]

public class doublePrecision {
public static void main(String[] args) {
double total = 0;
total += 5.6;
total += 5.8;
System.out.println(total);
}
}
The above code prints:
11.399999999999
How would I get this to just print (or be able to use it as) 11.4?
As others have mentioned, you'll probably want to use the BigDecimal class, if you want to have an exact representation of 11.4.
Now, a little explanation into why this is happening:
The float and double primitive types in Java are floating point numbers, where the number is stored as a binary representation of a fraction and a exponent.
More specifically, a double-precision floating point value such as the double type is a 64-bit value, where:
1 bit denotes the sign (positive or negative).
11 bits for the exponent.
52 bits for the significant digits (the fractional part as a binary).
These parts are combined to produce a double representation of a value.
(Source: Wikipedia: Double precision)
For a detailed description of how floating point values are handled in Java, see the Section 4.2.3: Floating-Point Types, Formats, and Values of the Java Language Specification.
The byte, char, int, long types are fixed-point numbers, which are exact representions of numbers. Unlike fixed point numbers, floating point numbers will some times (safe to assume "most of the time") not be able to return an exact representation of a number. This is the reason why you end up with 11.399999999999 as the result of 5.6 + 5.8.
When requiring a value that is exact, such as 1.5 or 150.1005, you'll want to use one of the fixed-point types, which will be able to represent the number exactly.
As has been mentioned several times already, Java has a BigDecimal class which will handle very large numbers and very small numbers.
From the Java API Reference for the BigDecimal class:
Immutable,
arbitrary-precision signed decimal
numbers. A BigDecimal consists of an
arbitrary precision integer unscaled
value and a 32-bit integer scale. If
zero or positive, the scale is the
number of digits to the right of the
decimal point. If negative, the
unscaled value of the number is
multiplied by ten to the power of the
negation of the scale. The value of
the number represented by the
BigDecimal is therefore (unscaledValue
× 10^-scale).
There has been many questions on Stack Overflow relating to the matter of floating point numbers and its precision. Here is a list of related questions that may be of interest:
Why do I see a double variable initialized to some value like 21.4 as 21.399999618530273?
How to print really big numbers in C++
How is floating point stored? When does it matter?
Use Float or Decimal for Accounting Application Dollar Amount?
If you really want to get down to the nitty gritty details of floating point numbers, take a look at What Every Computer Scientist Should Know About Floating-Point Arithmetic.
When you input a double number, for example, 33.33333333333333, the value you get is actually the closest representable double-precision value, which is exactly:
33.3333333333333285963817615993320941925048828125
Dividing that by 100 gives:
0.333333333333333285963817615993320941925048828125
which also isn't representable as a double-precision number, so again it is rounded to the nearest representable value, which is exactly:
0.3333333333333332593184650249895639717578887939453125
When you print this value out, it gets rounded yet again to 17 decimal digits, giving:
0.33333333333333326
If you just want to process values as fractions, you can create a Fraction class which holds a numerator and denominator field.
Write methods for add, subtract, multiply and divide as well as a toDouble method. This way you can avoid floats during calculations.
EDIT: Quick implementation,
public class Fraction {
private int numerator;
private int denominator;
public Fraction(int n, int d){
numerator = n;
denominator = d;
}
public double toDouble(){
return ((double)numerator)/((double)denominator);
}
public static Fraction add(Fraction a, Fraction b){
if(a.denominator != b.denominator){
double aTop = b.denominator * a.numerator;
double bTop = a.denominator * b.numerator;
return new Fraction(aTop + bTop, a.denominator * b.denominator);
}
else{
return new Fraction(a.numerator + b.numerator, a.denominator);
}
}
public static Fraction divide(Fraction a, Fraction b){
return new Fraction(a.numerator * b.denominator, a.denominator * b.numerator);
}
public static Fraction multiply(Fraction a, Fraction b){
return new Fraction(a.numerator * b.numerator, a.denominator * b.denominator);
}
public static Fraction subtract(Fraction a, Fraction b){
if(a.denominator != b.denominator){
double aTop = b.denominator * a.numerator;
double bTop = a.denominator * b.numerator;
return new Fraction(aTop-bTop, a.denominator*b.denominator);
}
else{
return new Fraction(a.numerator - b.numerator, a.denominator);
}
}
}
Observe that you'd have the same problem if you used limited-precision decimal arithmetic, and wanted to deal with 1/3: 0.333333333 * 3 is 0.999999999, not 1.00000000.
Unfortunately, 5.6, 5.8 and 11.4 just aren't round numbers in binary, because they involve fifths. So the float representation of them isn't exact, just as 0.3333 isn't exactly 1/3.
If all the numbers you use are non-recurring decimals, and you want exact results, use BigDecimal. Or as others have said, if your values are like money in the sense that they're all a multiple of 0.01, or 0.001, or something, then multiply everything by a fixed power of 10 and use int or long (addition and subtraction are trivial: watch out for multiplication).
However, if you are happy with binary for the calculation, but you just want to print things out in a slightly friendlier format, try java.util.Formatter or String.format. In the format string specify a precision less than the full precision of a double. To 10 significant figures, say, 11.399999999999 is 11.4, so the result will be almost as accurate and more human-readable in cases where the binary result is very close to a value requiring only a few decimal places.
The precision to specify depends a bit on how much maths you've done with your numbers - in general the more you do, the more error will accumulate, but some algorithms accumulate it much faster than others (they're called "unstable" as opposed to "stable" with respect to rounding errors). If all you're doing is adding a few values, then I'd guess that dropping just one decimal place of precision will sort things out. Experiment.
You may want to look into using java's java.math.BigDecimal class if you really need precision math. Here is a good article from Oracle/Sun on the case for BigDecimal. While you can never represent 1/3 as someone mentioned, you can have the power to decide exactly how precise you want the result to be. setScale() is your friend.. :)
Ok, because I have way too much time on my hands at the moment here is a code example that relates to your question:
import java.math.BigDecimal;
/**
* Created by a wonderful programmer known as:
* Vincent Stoessel
* xaymaca#gmail.com
* on Mar 17, 2010 at 11:05:16 PM
*/
public class BigUp {
public static void main(String[] args) {
BigDecimal first, second, result ;
first = new BigDecimal("33.33333333333333") ;
second = new BigDecimal("100") ;
result = first.divide(second);
System.out.println("result is " + result);
//will print : result is 0.3333333333333333
}
}
and to plug my new favorite language, Groovy, here is a neater example of the same thing:
import java.math.BigDecimal
def first = new BigDecimal("33.33333333333333")
def second = new BigDecimal("100")
println "result is " + first/second // will print: result is 0.33333333333333
Pretty sure you could've made that into a three line example. :)
If you want exact precision, use BigDecimal. Otherwise, you can use ints multiplied by 10 ^ whatever precision you want.
As others have noted, not all decimal values can be represented as binary since decimal is based on powers of 10 and binary is based on powers of two.
If precision matters, use BigDecimal, but if you just want friendly output:
System.out.printf("%.2f\n", total);
Will give you:
11.40
You're running up against the precision limitation of type double.
Java.Math has some arbitrary-precision arithmetic facilities.
You can't, because 7.3 doesn't have a finite representation in binary. The closest you can get is 2054767329987789/2**48 = 7.3+1/1407374883553280.
Take a look at http://docs.python.org/tutorial/floatingpoint.html for a further explanation. (It's on the Python website, but Java and C++ have the same "problem".)
The solution depends on what exactly your problem is:
If it's that you just don't like seeing all those noise digits, then fix your string formatting. Don't display more than 15 significant digits (or 7 for float).
If it's that the inexactness of your numbers is breaking things like "if" statements, then you should write if (abs(x - 7.3) < TOLERANCE) instead of if (x == 7.3).
If you're working with money, then what you probably really want is decimal fixed point. Store an integer number of cents or whatever the smallest unit of your currency is.
(VERY UNLIKELY) If you need more than 53 significant bits (15-16 significant digits) of precision, then use a high-precision floating-point type, like BigDecimal.
private void getRound() {
// this is very simple and interesting
double a = 5, b = 3, c;
c = a / b;
System.out.println(" round val is " + c);
// round val is : 1.6666666666666667
// if you want to only two precision point with double we
// can use formate option in String
// which takes 2 parameters one is formte specifier which
// shows dicimal places another double value
String s = String.format("%.2f", c);
double val = Double.parseDouble(s);
System.out.println(" val is :" + val);
// now out put will be : val is :1.67
}
Use java.math.BigDecimal
Doubles are binary fractions internally, so they sometimes cannot represent decimal fractions to the exact decimal.
/*
0.8 1.2
0.7 1.3
0.7000000000000002 2.3
0.7999999999999998 4.2
*/
double adjust = fToInt + 1.0 - orgV;
// The following two lines works for me.
String s = String.format("%.2f", adjust);
double val = Double.parseDouble(s);
System.out.println(val); // output: 0.8, 0.7, 0.7, 0.8
Doubles are approximations of the decimal numbers in your Java source. You're seeing the consequence of the mismatch between the double (which is a binary-coded value) and your source (which is decimal-coded).
Java's producing the closest binary approximation. You can use the java.text.DecimalFormat to display a better-looking decimal value.
Short answer: Always use BigDecimal and make sure you are using the constructor with String argument, not the double one.
Back to your example, the following code will print 11.4, as you wish.
public class doublePrecision {
public static void main(String[] args) {
BigDecimal total = new BigDecimal("0");
total = total.add(new BigDecimal("5.6"));
total = total.add(new BigDecimal("5.8"));
System.out.println(total);
}
}
Multiply everything by 100 and store it in a long as cents.
Computers store numbers in binary and can't actually represent numbers such as 33.333333333 or 100.0 exactly. This is one of the tricky things about using doubles. You will have to just round the answer before showing it to a user. Luckily in most applications, you don't need that many decimal places anyhow.
Floating point numbers differ from real numbers in that for any given floating point number there is a next higher floating point number. Same as integers. There's no integer between 1 and 2.
There's no way to represent 1/3 as a float. There's a float below it and there's a float above it, and there's a certain distance between them. And 1/3 is in that space.
Apfloat for Java claims to work with arbitrary precision floating point numbers, but I've never used it. Probably worth a look.
http://www.apfloat.org/apfloat_java/
A similar question was asked here before
Java floating point high precision library
Use a BigDecimal. It even lets you specify rounding rules (like ROUND_HALF_EVEN, which will minimize statistical error by rounding to the even neighbor if both are the same distance; i.e. both 1.5 and 2.5 round to 2).
Why not use the round() method from Math class?
// The number of 0s determines how many digits you want after the floating point
// (here one digit)
total = (double)Math.round(total * 10) / 10;
System.out.println(total); // prints 11.4
Check out BigDecimal, it handles problems dealing with floating point arithmetic like that.
The new call would look like this:
term[number].coefficient.add(co);
Use setScale() to set the number of decimal place precision to be used.
If you have no choice other than using double values, can use the below code.
public static double sumDouble(double value1, double value2) {
double sum = 0.0;
String value1Str = Double.toString(value1);
int decimalIndex = value1Str.indexOf(".");
int value1Precision = 0;
if (decimalIndex != -1) {
value1Precision = (value1Str.length() - 1) - decimalIndex;
}
String value2Str = Double.toString(value2);
decimalIndex = value2Str.indexOf(".");
int value2Precision = 0;
if (decimalIndex != -1) {
value2Precision = (value2Str.length() - 1) - decimalIndex;
}
int maxPrecision = value1Precision > value2Precision ? value1Precision : value2Precision;
sum = value1 + value2;
String s = String.format("%." + maxPrecision + "f", sum);
sum = Double.parseDouble(s);
return sum;
}
You can Do the Following!
System.out.println(String.format("%.12f", total));
if you change the decimal value here %.12f
So far I understand it as main goal to get correct double from wrong double.
Look for my solution how to get correct value from "approximate" wrong value - if it is real floating point it rounds last digit - counted from all digits - counting before dot and try to keep max possible digits after dot - hope that it is enough precision for most cases:
public static double roundError(double value) {
BigDecimal valueBigDecimal = new BigDecimal(Double.toString(value));
String valueString = valueBigDecimal.toPlainString();
if (!valueString.contains(".")) return value;
String[] valueArray = valueString.split("[.]");
int places = 16;
places -= valueArray[0].length();
if ("56789".contains("" + valueArray[0].charAt(valueArray[0].length() - 1))) places--;
//System.out.println("Rounding " + value + "(" + valueString + ") to " + places + " places");
return valueBigDecimal.setScale(places, RoundingMode.HALF_UP).doubleValue();
}
I know it is long code, sure not best, maybe someone can fix it to be more elegant. Anyway it is working, see examples:
roundError(5.6+5.8) = 11.399999999999999 = 11.4
roundError(0.4-0.3) = 0.10000000000000003 = 0.1
roundError(37235.137567000005) = 37235.137567
roundError(1/3) 0.3333333333333333 = 0.333333333333333
roundError(3723513756.7000005) = 3.7235137567E9 (3723513756.7)
roundError(3723513756123.7000005) = 3.7235137561237E12 (3723513756123.7)
roundError(372351375612.7000005) = 3.723513756127E11 (372351375612.7)
roundError(1.7976931348623157) = 1.797693134862316
Do not waste your efford using BigDecimal. In 99.99999% cases you don't need it. java double type is of cource approximate but in almost all cases, it is sufficiently precise. Mind that your have an error at 14th significant digit. This is really negligible!
To get nice output use:
System.out.printf("%.2f\n", total);

BigInteger Sqrt Function isn't converging

I am currently writing a function to find the square root of a given BigInteger. The current number in my test file is 250074134890485729738. The program however always stalls while finding the sqrt at 15813732488, which squared is 250074135202026670144. I have copied this
code from another StackOverflow problem, and it ceases converging at the same number. It uses Newtons Method, while I'm using the Babylonian/Heron's Method.
Their Code:
public static BigInteger sqrtN(BigInteger in) {
final BigInteger TWO = BigInteger.valueOf(2);
int c;
// Significantly speed-up algorithm by proper select of initial approximation
// As square root has 2 times less digits as original value
// we can start with 2^(length of N1 / 2)
BigInteger n0 = TWO.pow(in.bitLength() / 2);
// Value of approximate value on previous step
BigInteger np = in;
do {
// next approximation step: n0 = (n0 + in/n0) / 2
n0 = n0.add(in.divide(n0)).divide(TWO);
// compare current approximation with previous step
c = np.compareTo(n0);
// save value as previous approximation
np = n0;
// finish when previous step is equal to current
} while (c != 0);
return n0;}
My Code:
static BigInteger number;
static BigInteger sqrt;
public static void main(String[] args) throws Exception {
number = new BigInteger(getFile());
System.out.println("Factoring: \n\n" + number);
sqrt = sqrt();
System.out.println("The root is: " + sqrt.toString());
System.out.println("Test, should equal nearest square at or above original number: " + sqrt.multiply(sqrt).toString() + "\nOriginal number: " + number.toString());
}
public static BigInteger sqrt() {
BigInteger guess = number.divide(new BigInteger("500"));
BigInteger TWO = new BigInteger("2");
BigInteger HUNDRED = new BigInteger("100");
boolean go = true;
while (number.subtract((guess.multiply(guess))).abs().compareTo(HUNDRED) == 1 && go){
BigInteger numOne = guess.divide(TWO);
BigInteger numTwo = number.divide(guess.multiply(TWO));
guess = numOne.add(numTwo);
if (numOne.equals(numTwo))
go = false;
System.out.println(guess.toString());
}
return guess.add(BigInteger.ONE);
My Output:
Factoring:
250074134890485729738
250074134890485979
125037067445243488
62518533722622743
31259266861313370
15629633430660684
7814816715338341
3907408357685169
1953704178874583
976852089501290
488426044878644
244213022695321
122106511859659
61053256953828
30526630524913
15263319358455
7631667871224
3815850319588
1907957927606
954044498302
477153309146
238838702566
119942872245
61013907968
32556274730
20118781556
16274333124
15820250501
15813733820
15813732478
15813732478
The root is: 15813732479
Test, should equal nearest square at or above original number: 250074134917379485441
Original number: 250074134890485729738
A couple notes:
I had a couple of ideas while writing this and I tried them. If something doesn't match up, that's my fault. I did check, but I'm not perfect.
While I appreciate people being generous enough to point me towards a different piece of pre-written code/post their own, this (while not school work) is a learning experience for me. PLEASE DO post how this code could be fixed, PLEASE DO NOT just post a different piece of code that does the same.
ANSWER: This actually does work as is, the original input is simply not a perfect square. Therefore, this works perfectly for my purposes. Thanks to all who wasted their time due to my incompetence. I have changed the code to return a value equivalent to (if Math.sqrt/ceil worked on BigInts):
sqrt = Math.Ceil(Math.Sqrt(A_RANDOM_BIGINTEGER_HERE));
I have also removed unnecessary variables, and updated the output to match. Both these methods work fine, although the first one requires some code to catch the non-convergence cycle, in case any future visitors to this question wish to use them.
15813732478 is the square root of 250074134890485729738, at least the integral part of it. The real square root is 15813732478.149670840219509075711, according to calc.
There are two problems:
You are looping 100 times instead of stopping at convergence.
Your assumption that sqrt(N)*sqrt(N) = N is fallacious, because you're only computing the integral part, so there will be an error proportional to N.
You have in your while loop in your sqrt() function a compareTo(100) which (I suspect) is always returning 1 ie the absolute value of number minus the guess squared is always greater than 100.
Which after testing I see that it is, add this at the end of your loop and you'll see that the difference once you reach the root is still very large = 4733709254
At this point numOne and numTwo become the same value so guess is always the same for each subsequent iteration also.
System.out.println("Squaring:" + guess.multiply(guess).toString() +
"; Substracting: " + number.subtract((guess.multiply(guess))).toString());
You also have c < 100 so if that comparison is always true then it will always print 100 lines.

Dealing with overflow in Java without using BigInteger

Suppose I have a method to calculate combinations of r items from n items:
public static long combi(int n, int r) {
if ( r == n) return 1;
long numr = 1;
for(int i=n; i > (n-r); i--) {
numr *=i;
}
return numr/fact(r);
}
public static long fact(int n) {
long rs = 1;
if(n <2) return 1;
for (int i=2; i<=n; i++) {
rs *=i;
}
return rs;
}
As you can see it involves factorial which can easily overflow the result. For example if I have fact(200) for the foctorial method I get zero. The question is why do I get zero?
Secondly how do I deal with overflow in above context? The method should return largest possible number to fit in long if the result is too big instead of returning wrong answer.
One approach (but this could be wrong) is that if the result exceed some large number for example 1,400,000,000 then return remainder of result modulo
1,400,000,001. Can you explain what this means and how can I do that in Java?
Note that I do not guarantee that above methods are accurate for calculating factorial and combinations. Extra bonus if you can find errors and correct them.
Note that I can only use int or long and if it is unavoidable, can also use double. Other data types are not allowed.
I am not sure who marked this question as homework. This is NOT homework. I wish it was homework and i was back to future, young student at university. But I am old with more than 10 years working as programmer. I just want to practice developing highly optimized solutions in Java. In our times at university, Internet did not even exist. Today's students are lucky that they can even post their homework on site like SO.
Use the multiplicative formula, instead of the factorial formula.
Since its homework, I won't want to just give you a solution. However a hint I will give is that instead of calculating two large numbers and dividing the result, try calculating both together. e.g. calculate the numerator until its about to over flow, then calculate the denominator. In this last step you can chose the divide the numerator instead of multiplying the denominator. This stops both values from getting really large when the ratio of the two is relatively small.
I got this result before an overflow was detected.
combi(61,30) = 232714176627630544 which is 2.52% of Long.MAX_VALUE
The only "bug" I found in your code is not having any overflow detection, since you know its likely to be a problem. ;)
To answer your first question (why did you get zero), the values of fact() as computed by modular arithmetic were such that you hit a result with all 64 bits zero! Change your fact code to this:
public static long fact(int n) {
long rs = 1;
if( n <2) return 1;
for (int i=2; i<=n; i++) {
rs *=i;
System.out.println(rs);
}
return rs;
}
Take a look at the outputs! They are very interesting.
Now onto the second question....
It looks like you want to give exact integer (er, long) answers for values of n and r that fit, and throw an exception if they do not. This is a fair exercise.
To do this properly you should not use factorial at all. The trick is to recognize that C(n,r) can be computed incrementally by adding terms. This can be done using recursion with memoization, or by the multiplicative formula mentioned by Stefan Kendall.
As you accumulate the results into a long variable that you will use for your answer, check the value after each addition to see if it goes negative. When it does, throw an exception. If it stays positive, you can safely return your accumulated result as your answer.
To see why this works consider Pascal's triangle
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
which is generated like so:
C(0,0) = 1 (base case)
C(1,0) = 1 (base case)
C(1,1) = 1 (base case)
C(2,0) = 1 (base case)
C(2,1) = C(1,0) + C(1,1) = 2
C(2,2) = 1 (base case)
C(3,0) = 1 (base case)
C(3,1) = C(2,0) + C(2,1) = 3
C(3,2) = C(2,1) + C(2,2) = 3
...
When computing the value of C(n,r) using memoization, store the results of recursive invocations as you encounter them in a suitable structure such as an array or hashmap. Each value is the sum of two smaller numbers. The numbers start small and are always positive. Whenever you compute a new value (let's call it a subterm) you are adding smaller positive numbers. Recall from your computer organization class that whenever you add two modular positive numbers, there is an overflow if and only if the sum is negative. It only takes one overflow in the whole process for you to know that the C(n,r) you are looking for is too large.
This line of argument could be turned into a nice inductive proof, but that might be for another assignment, and perhaps another StackExchange site.
ADDENDUM
Here is a complete application you can run. (I haven't figured out how to get Java to run on codepad and ideone).
/**
* A demo showing how to do combinations using recursion and memoization, while detecting
* results that cannot fit in 64 bits.
*/
public class CombinationExample {
/**
* Returns the number of combinatios of r things out of n total.
*/
public static long combi(int n, int r) {
long[][] cache = new long[n + 1][n + 1];
if (n < 0 || r > n) {
throw new IllegalArgumentException("Nonsense args");
}
return c(n, r, cache);
}
/**
* Recursive helper for combi.
*/
private static long c(int n, int r, long[][] cache) {
if (r == 0 || r == n) {
return cache[n][r] = 1;
} else if (cache[n][r] != 0) {
return cache[n][r];
} else {
cache[n][r] = c(n-1, r-1, cache) + c(n-1, r, cache);
if (cache[n][r] < 0) {
throw new RuntimeException("Woops too big");
}
return cache[n][r];
}
}
/**
* Prints out a few example invocations.
*/
public static void main(String[] args) {
String[] data = ("0,0,3,1,4,4,5,2,10,0,10,10,10,4,9,7,70,8,295,100," +
"34,88,-2,7,9,-1,90,0,90,1,90,2,90,3,90,8,90,24").split(",");
for (int i = 0; i < data.length; i += 2) {
int n = Integer.valueOf(data[i]);
int r = Integer.valueOf(data[i + 1]);
System.out.printf("C(%d,%d) = ", n, r);
try {
System.out.println(combi(n, r));
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
}
Hope it is useful. It's just a quick hack so you might want to clean it up a little.... Also note that a good solution would use proper unit testing, although this code does give nice output.
You can use the java.math.BigInteger class to deal with arbitrarily large numbers.
If you make the return type double, it can handle up to fact(170), but you'll lose some precision because of the nature of double (I don't know why you'd need exact precision for such huge numbers).
For input over 170, the result is infinity
Note that java.lang.Long includes constants for the min and max values for a long.
When you add together two signed 2s-complement positive values of a given size, and the result overflows, the result will be negative. Bit-wise, it will be the same bits you would have gotten with a larger representation, only the high-order bit will be truncated away.
Multiplying is a bit more complicated, unfortunately, since you can overflow by more than one bit.
But you can multiply in parts. Basically you break the to multipliers into low and high halves (or more than that, if you already have an "overflowed" value), perform the four possible multiplications between the four halves, then recombine the results. (It's really just like doing decimal multiplication by hand, but each "digit" is, say, 32 bits.)
You can copy the code from java.math.BigInteger to deal with arbitrarily large numbers. Go ahead and plagiarize.

Compute Logarithm

I'm trying to write a method that takes in a base k and a value n to 2 decimal places, then computes the log base k of n without using any of Java's Math.log methods. Here's what I have so far:
public static double log(double k, double n) {
double value = 0.0;
for(double i = 1; i > .001; i /= 10) {
while(!(Math.pow(k, value) >= n )) {
value += i;
}
}
return value;
}
The problem comes up when I try computing log base 4 of 5.0625, which returns 2.0, but should return 1.5.
I have no idea why this isn't working. Any help is appreciated.
No this is not homework, it's part of a problem set that I'm trying to solve for fun.
You're adding the amount i once too ofter. Thus you'll quite soon reach a value larger than the actual value and the while loop will never be entered again.
Subtract i once from the value and you'll be fine:
for(double i = 1; i > .001; i /= 10) {
while(!(Math.pow(k, value) > n )) {
value += i;
}
value -= i;
}
Step through the code on paper:
Iteration: i=1 value = 0.0, calculated power = 1
Iteration: i=1 value = 1.0, calculated power = 4
Iteration: i=1 value = 2.0, calculated power = 16
Now at this point, your value is 2.0. But at no point in the code to you have a way to correct back in the other direction. You need to check for both overshoot and undershoot cases.
This loop
while(!(Math.pow(k, value) >= n )) {
value += i;
}
goes too far. It only stops after the correct value has been surpassed. So when calculating the ones place, 1 isn't enough, so it goes to 2.0, and all subsequent tests show that it is at least enough, so that's where it ends.
Calculating logs by hand, what fun! I suggest doing it out on paper, then stepping through your code with watch variables or outputting each variable at each step. Then check this method out and see if it lines up with what you're doing: Link
You could always look at:
https://stackoverflow.com/a/2073928/251767
It provides an algorithm which will compute a log of any number in any base. It's a response to a question about calculating logs with BigDecimal types, but it could be adapted, pretty easily, to any floating-point type.
Since it uses squaring and dividing by two, instead of using multiple calls to Math.pow(), it should converge pretty quickly and use less CPU resources.

Make a negative number positive

I have a Java method in which I'm summing a set of numbers. However, I want any negatives numbers to be treated as positives. So (1)+(2)+(1)+(-1) should equal 5.
I'm sure there is very easy way of doing this - I just don't know how.
Just call Math.abs. For example:
int x = Math.abs(-5);
Which will set x to 5.
Note that if you pass Integer.MIN_VALUE, the same value (still negative) will be returned, as the range of int does not allow the positive equivalent to be represented.
The concept you are describing is called "absolute value", and Java has a function called Math.abs to do it for you. Or you could avoid the function call and do it yourself:
number = (number < 0 ? -number : number);
or
if (number < 0)
number = -number;
You're looking for absolute value, mate. Math.abs(-5) returns 5...
Use the abs function:
int sum=0;
for(Integer i : container)
sum+=Math.abs(i);
Try this (the negative in front of the x is valid since it is a unary operator, find more here):
int answer = -x;
With this, you can turn a positive to a negative and a negative to a positive.
However, if you want to only make a negative number positive then try this:
int answer = Math.abs(x);
A little cool math trick! Squaring the number will guarantee a positive value of x^2, and then, taking the square root will get you to the absolute value of x:
int answer = Math.sqrt(Math.pow(x, 2));
Hope it helps! Good Luck!
This code is not safe to be called on positive numbers.
int x = -20
int y = x + (2*(-1*x));
// Therefore y = -20 + (40) = 20
Are you asking about absolute values?
Math.abs(...) is the function you probably want.
You want to wrap each number into Math.abs(). e.g.
System.out.println(Math.abs(-1));
prints out "1".
If you want to avoid writing the Math.-part, you can include the Math util statically. Just write
import static java.lang.Math.abs;
along with your imports, and you can refer to the abs()-function just by writing
System.out.println(abs(-1));
The easiest, if verbose way to do this is to wrap each number in a Math.abs() call, so you would add:
Math.abs(1) + Math.abs(2) + Math.abs(1) + Math.abs(-1)
with logic changes to reflect how your code is structured. Verbose, perhaps, but it does what you want.
When you need to represent a value without the concept of a loss or absence (negative value), that is called "absolute value".
The logic to obtain the absolute value is very simple: "If it's positive, maintain it. If it's negative, negate it".
What this means is that your logic and code should work like the following:
//If value is negative...
if ( value < 0 ) {
//...negate it (make it a negative negative-value, thus a positive value).
value = negate(value);
}
There are 2 ways you can negate a value:
By, well, negating it's value: value = (-value);
By multiplying it by "100% negative", or "-1": value = value *
(-1);
Both are actually two sides of the same coin. It's just that you usually don't remember that value = (-value); is actually value = 1 * (-value);.
Well, as for how you actually do it in Java, it's very simple, because Java already provides a function for that, in the Math class: value = Math.abs(value);
Yes, doing it without Math.abs() is just a line of code with very simple math, but why make your code look ugly? Just use Java's provided Math.abs() function! They provide it for a reason!
If you absolutely need to skip the function, you can use value = (value < 0) ? (-value) : value;, which is simply a more compact version of the code I mentioned in the logic (3rd) section, using the Ternary operator (? :).
Additionally, there might be situations where you want to always represent loss or absence within a function that might receive both positive and negative values.
Instead of doing some complicated check, you can simply get the absolute value, and negate it: negativeValue = (-Math.abs(value));
With that in mind, and considering a case with a sum of multiple numbers such as yours, it would be a nice idea to implement a function:
int getSumOfAllAbsolutes(int[] values){
int total = 0;
for(int i=0; i<values.lenght; i++){
total += Math.abs(values[i]);
}
return total;
}
Depending on the probability you might need related code again, it might also be a good idea to add them to your own "utils" library, splitting such functions into their core components first, and maintaining the final function simply as a nest of calls to the core components' now-split functions:
int[] makeAllAbsolute(int[] values){
//#TIP: You can also make a reference-based version of this function, so that allocating 'absolutes[]' is not needed, thus optimizing.
int[] absolutes = values.clone();
for(int i=0; i<values.lenght; i++){
absolutes[i] = Math.abs(values[i]);
}
return absolutes;
}
int getSumOfAllValues(int[] values){
int total = 0;
for(int i=0; i<values.lenght; i++){
total += values[i];
}
return total;
}
int getSumOfAllAbsolutes(int[] values){
return getSumOfAllValues(makeAllAbsolute(values));
}
Why don't you multiply that number with -1?
Like This:
//Given x as the number, if x is less than 0, return 0 - x, otherwise return x:
return (x <= 0.0F) ? 0.0F - x : x;
If you're interested in the mechanics of two's complement, here's the absolutely inefficient, but illustrative low-level way this is made:
private static int makeAbsolute(int number){
if(number >=0){
return number;
} else{
return (~number)+1;
}
}
Library function Math.abs() can be used.
Math.abs() returns the absolute value of the argument
if the argument is negative, it returns the negation of the argument.
if the argument is positive, it returns the number as it is.
e.g:
int x=-5;
System.out.println(Math.abs(x));
Output: 5
int y=6;
System.out.println(Math.abs(y));
Output: 6
String s = "-1139627840";
BigInteger bg1 = new BigInteger(s);
System.out.println(bg1.abs());
Alternatively:
int i = -123;
System.out.println(Math.abs(i));
To convert negative number to positive number (this is called absolute value), uses Math.abs(). This Math.abs() method is work like this
“number = (number < 0 ? -number : number);".
In below example, Math.abs(-1) will convert the negative number 1 to positive 1.
example
public static void main(String[] args) {
int total = 1 + 1 + 1 + 1 + (-1);
//output 3
System.out.println("Total : " + total);
int total2 = 1 + 1 + 1 + 1 + Math.abs(-1);
//output 5
System.out.println("Total 2 (absolute value) : " + total2);
}
Output
Total : 3
Total 2 (absolute value) : 5
I would recommend the following solutions:
without lib fun:
value = (value*value)/value
(The above does not actually work.)
with lib fun:
value = Math.abs(value);
I needed the absolute value of a long , and looked deeply into Math.abs and found that if my argument is less than LONG.MIN_VAL which is -9223372036854775808l, then the abs function would not return an absolute value but only the minimum value. Inthis case if your code is using this abs value further then there might be an issue.
Can you please try this one?
public static int toPositive(int number) {
return number & 0x7fffffff;
}
if(arr[i]<0)
Math.abs(arr[i]); //1st way (taking absolute value)
arr[i]=-(arr[i]); //2nd way (taking -ve of -ve no. yields a +ve no.)
arr[i]= ~(arr[i]-1); //3rd way (taking negation)
I see people are saying that Math.abs(number) but this method is not full proof.
This fails when you try to wrap Math.abs(Integer.MIN_VALUE) (see ref. https://youtu.be/IWrpDP-ad7g)
If you are not sure whether you are going to receive the Integer.MIN_VALUE in the input. It is always recommended to check for that number and handle it manually.
In kotlin you can use unaryPlus
input = input.unaryPlus()
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/unary-plus.html
Try this in the for loop:
sum += Math.abs(arr[i])
dont do this
number = (number < 0 ? -number : number);
or
if (number < 0) number = -number;
this will be an bug when you run find bug on your code it will report it as RV_NEGATING_RESULT_OF

Categories