How to round doubles to a specified decimal place without Libraries? - java

Basically I'm supposed to write a method, that uses a double "x" and an int "y" and rounds (>=5 upwards, <5 downwards) "x" to the decimal place specified by y (between 1-8). The method is supposed to return a double. However since I just started I don't have a clue how to achieve this. The exercise prior to this one way easier.
If read answers to similar question but they are not quit what I need, because I can't use the Math library or other libraries. I'm allowed to make auxiliary methods to substitute this.

Rounding like that with double isn't going to work. Doubles and floats are represented with a fixed number of bits of data, and work in binary not decimal. That means that some numbers can't be represented. .1 can't be stored exactly.
In order to do this, you need to do use BigDecimal, which is a class that can store any exact number. Math using BigDecimal is less efficient, but it doesn't have the accuracy issues of doubles.

Related

Java and unlimited decimal places?

Is there a simple way that i can manipulate high precision decimal numbers in java, without a limit on the number of decimal places, and the ability to output the number in a println or write it to a file? I want to work with one of the identities of PI that involves a sum of fractions, where k starts at 0 and goes to infinity. I know that most systems use limited decimals, but couldn't i use some pre-designed class which stores the value as a linked list of massive memory blocks if the number gets long enough? Please keep in mind i do need to do arithmetic with this class as well. Addition, subtraction, multiplication, and division should be sufficient.
I believe that you are looking for the java.lang.BigDecimal class.
Look at java.lang.BigDecimal, may solve your problem.
http://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html

Using Java doubles (or anything else) to store simple fractions [duplicate]

This question already has answers here:
Division of integers in Java [duplicate]
(7 answers)
Closed 7 years ago.
This seems like a very simple error:
double quarter = 1/4;
Is giving
0.0
Anybody know why this might be happening?
I am trying to store pretty much all the fractions from 1/2 to 1/20 (Just the ones with 1 on the top and in int on the bottom), so I won't be able to input the decimal straight away for all of them.
I've read and heard that floating-point datatypes are not a good way of storing fractions, so is there any other way (in Java)?
Try:
double quarter = 1d/4d;
The division of two integers gives a truncated integer. By putting the d behind the numbers you are casting them to doubles.
For starters, you're trying to divide 1/4 as integer values, and it's truncating it. 1. / 4 will correctly give you 0.25; other ways to express the number 1 as a double include 1d, 1.0, and so on.
Other approaches include:
Use BigDecimal to store values to an exact decimal precision. (For example, this is the preferred way to deal with monetary values.)
Use a Fraction or Rational class, either rolling your own or using one from a library. Apache Commons has Fraction and BigFraction, though their documentation seems a little sketchy.
Java is performing integer division because your denominator is an integer.
Try the following:
double quarter = 1 / 4.0;
Or:
double quarter = 1 / (double) 4;
The reason you're getting 0.0 is because the division is done as an integer division and then the result is converted to float. Try this, for example: double quarter = 1.0/4.0; - you should get (pretty much) the expected result.
However, depending on your requirements, this may not be the best way to deal with the problem. For example, you can't store 1/3 in a decimal. The perfect way would be to store simple fraction as a pair of integers. You can create a class for it (with some arithmetic methods) or start by using a simple array. It all depends on your needs.

Is there a rounding algorithm that undoes base 2 conversion and infers precision? *hopefully in java*

If I have a number like 3.01 the computer seems to think the best double is the 64 bit number:
3.0099999999999997868371792719699442386627197265625
Is there some way better than looking for say more than four 9's or 0's that I can generically "round" to the precise base 10 representation?
Is there an algo that would take that 3.00999999... mess and return 3.01 WITHOUT me specifying that I want that precision.
I think most of the numbers I'm dealing with should be small enough that 64-bits will not have ambiguities.
No - because presumably you might have actually specified 3.0099999999999997868 as the input number, and wouldn't want that same value to be rounded to 3.01. Basically, you've lost information when converting from a decimal value to binary floating point - you can't get that information back.
If you're interested in decimal values rather than just the magnitude, you should consider using BigDecimal instead of double. (What do these values represent?)
EDIT: As noted by other answers, Java will give you 3.01 anyway when you just use toString, however you came to the original value. This is specified in 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.
If that's good enough for you, it'll make life easier... but it sounds like you should be thinking about it more fundamentally.
If you want 10 digits of precision, you need to round to that precision. Even if you use BigDecimal you can avoid representation error, but sooner or later you will have to know how to deal with precision.
double d = 3.01;
System.out.println(d); // rounds the answer slightly
prints
3.01
There are many workarounds for representation and rounding error, however often the built in tools will deal with it for you.
It's clear that you cannot expect to always get the original number back since there are many numbers that map to the same float. For example, you cannot distinguish between these numbers:
3.0099999999999997868371792719699442386627197265625
3.009999999999999786837179271969944238662
3.009999999999999786837179271
3.0099999999999997
3.01
However, Python has an interesting take on this: if you give it the number 3.0099999999999997868371792719699442386627197265625, it will reply with 3.01:
Python 2.7.2+ (default, Nov 30 2011, 19:22:03)
[GCC 4.6.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 3.0099999999999997868371792719699442386627197265625
3.01
This is becauuse 3.01 is the shortest string that gives the same floating point number. In other words, it's the shortest x so that
float(repr(x)) == x
where repr is the Python function that turns an object into a string (here it turns 3.0099... into 3.01) and float converts a string to a float.
There are obvisouly many strings that will result in the same internal float, but this is the shortest and therefore "probably" what you meant.
This feature was added in Python 2.7, as a backport of a Python 3.1 feature. It was discussed in Issue1580 and you should be able to find the code there and translate it into Java if you want.

Java Math.pow issue

I am working on a program which needs to cube a number. Long story short, I need to compare the number to a string, so I need to get rid of the decimal place a double gives when I convert to string. To do this, I used Math.round and saved it as a long. This works fine for relatively normal numbers, but the numbers can go up to 999,999.
I used 275393 (a given test number, so I'm assuming it must be correct for the problem I'm working on) and neither a calculator nor the computer seemed to get the correct answer. The correct answer is supposed to contain 123457 somewhere in the results, but the calculator has 12346 (which I think is just rounding, as it stops listing numbers after this) and the computer has 123456 (the computer stops listing numbers after this point). Is rounding it giving it the problem (it shouldn't because I'm pretty sure it only rounds to the tenths place, but who knows)? Or is it something else?
Math.pow() takes two doubles and returns a double. There is not enough precision in a double to represent 2753933 = 20886164356123457 (exact).
The solution is to use BigInteger.pow().
A double has limited precision. Instead, use BigInteger or BigDecimal for your calculation.
I need to compare the number to a string, so I need to get rid of the decimal place a double gives when I convert to string.
Do it the other way around. Convert the String to a number, then compare it to the double (with a small tolerance to account for inaccurate binary representations of float point numbers).

Four questions - Calculator Application - Android Java

Hey all, I am a total newbie developing an android application, I've been reading 'Sams Teach Yourself Java in 24 hours' and it's a great book. But I have been stuck on a bit where I get the value of a decimal number only editTexts and use java maths to work out my end value.
Is there a way to have an editText input straight to a float or double variable rather than to a string and then from a string to a double?
Are there any real issues with converting between a string and a double or float or will the values remain the same and not be polluted.
Differences / pros and cons of using a doble as opposed to a float.
Best way to input a fraction value from the user?
Thanks for any help. Have a good day.
No, you can't.
Yes. If your string is, say, an ID and reads like "0029482", after you turn it into an integer it will read "29482" and probably will be invalid. Strings can be longer than doubles or floats, and if you have a value like "0.12345678901234567890123456789" in a string, you will lose a lot of precision by converting that to a double.
Doubles use double the number of bits (hence the name), and can therefore hold more precision.
Accept the denominator and numerator integers, and store them in a custom class.
No. You could write your own subclass that makes it seem like that is what's happening, but at some point somewhere in the chain you have to do a conversion from character/text data to numerical data.
Yes. Primitive floating-point types use IEEE-754 to encode decimal numbers in binary. The encoding provides very good precision, but it is not exact/cannot exactly represent many possible numbers. So if you parse from a string to a primitive floating-point type, and then back to string again, you may get something that is different from your input string.
A double uses twice as many bits to encode the number as a float, and thus is able to maintain a greater degree of precision. It will not, however, remove the issues discussed in #2. If you want to remove those issues, consider using something like BigDecimal to represent your numbers instead of primitive types like float or double.
Read the whole thing as a string, split() it on the '/' character, and then store each part as an integer (or BigInteger). If you need to display it as a decimal, use BigDecimal to perform the division.
I'd just like to add that if you are looking for an alternative to double or float that doesn't entail loss of precision when converting between strings and numeric form, look at these:
The standard java.math.BigDecimal class represents an arbitrary precision scaled number; i.e. an arbitrary precision integer multiplied (scaled) by a fixed integer power of 10.
The Apache dfp package contains implementations of decimal-based floating numbers.
However, I'd steer clear of both of this topic for now, and implement using float or double. (I take it that your real aim is to learn how to write Java, not to build the world's greatest calculator app.)

Categories