I'm using below two statements :-
double foo = 20.00
float bar = 20.00
println foo == bar
And
double foo = 20.01
float bar = 20.01
println foo == bar
It gives the output as :-
true
false
Can anyone know what makes difference between these two statements?
double and float values don't have an exact internal representation for every value. The only decimal values that can be represented as an IEEE-754 binary floating-point for two decimal points are 0, 0.25, 0.5, 0.75 and 1. The rest of representations will always be slightly off, with small differences between doubles and floats creating this inequality behaviour.
This is not just valid for Groovy, but for Java as well.
For example:
double foo = 20.25
float bar = 20.25
println foo == bar
Output:
true
The 0.1 part of 20.01 is infinite repeating in binary; 20.01 =
10100.00000010100011110101110000101000111101011100001010001111010111...
floats are rounded (to nearest) to 24 significant bits; doubles are rounded to 53. That makes the float
10100.0000001010001111011
and the double
10100.000000101000111101011100001010001111010111000011
In decimal, those are
20.0100002288818359375 and
20.010000000000001563194018672220408916473388671875, respectively.
(You could see this directly using my decimal to floating-point converter.)
The Groovy Float aren't kept in the memory precisely. That is the main cause for the differences you have.
In Groovy the definition of the precision by the number of digits after the right side of the dot can be achieved by the following method signature:
public float trunc(int precision)
precision - the number of decimal places to keep.
For more details please follow the Class Float documentation.
It is more prefered to use BigDecimal class as a floating number when using the Groovy language.
The conversion from Number to String is much easier and there is the option to define the precision of the floating number **in the constructor.
BigDecimal(BigInteger unscaledVal, int scale)
Translates a BigInteger unscaled value and an int scale into a BigDecimal.
For more details please follow the Java BigDecimal documentation. As the Groovy language is based on the Java language. More over the BigDecimal will represent the exact value of the number.
Related
Need some help on the below piece of code that I am working on. Why original number in "a" is different from "c" when it goes through a type conversion. Any way we can make "a" and "c" same when it goes through float -> int type conversion?
a = '46700000000987654321'
b = float(a) => 4.670000000098765e+19
c = int(b) => 46700000000987652096
a == c => False
Please read this document about Floating Point Arithmetic: Issues and Limitations :
https://docs.python.org/3/tutorial/floatingpoint.html
for your example:
from decimal import Decimal
a='46700000000987654321'
b=Decimal(a)
print(b) #46700000000987654321
c=int(b)
print(c) #46700000000987654321
Modified version of my answer to another question (reasonably) duped to this one:
This happens because 46700000000987654321 is greater than the integer representational limits of a C double (which is what a Python float is implemented in terms of).
Typically, C doubles are IEEE 754 64 bit binary floating point values, which means they have 53 bits of integer precision (the last consecutive integer values float can represent are 2 ** 53 - 1 followed by 2 ** 53; it can't represent 2 ** 53 + 1). Problem is, 46700000000987654321 requires 66 bits of integer precision to store ((46700000000987654321).bit_length() will provide this information). When a value is too large for the significand (the integer component) alone, the exponent component of the floating point value is used to scale a smaller integer value by powers of 2 to be roughly in the ballpark of the original value, but this means that the representable integers start to skip, first by 2 (as you require >53 bits), then by 4 (for >54 bits), then 8 (>55 bits), then 16 (>56 bits), etc., skipping twice as far between representable values for each additional bit of magnitude you have beyond 53 bits.
In your case, 46700000000987654321, converted to float, has an integer value of 46700000000987652096 (as you noted), having lost precision in the low digits.
If you need arbitrarily precise base-10 floating point math, replace your use of float with decimal.Decimal (conveniently, your initial value is already a string, so you don't risk loss of precision between how you type a float and the actual value stored); the default precision will handle these values, and you can increase it if you need larger values. If you do that (and convert a to an int for the comparison, since a str is never equal to any numeric type), you get the behavior you expected:
from decimal import Decimal as Dec, getcontext
a = "46700000000987654321"
b = Dec(a); print(b) # => 46700000000987654321
c = int(b); print(c) # => 46700000000987654321
print(int(a) == c) # => True
Try it online!
If you echo the Decimals in an interactive interpreter instead of using print, you'd see Decimal('46700000000987654321') instead, which is the repr form of Decimals, but it's numerically 46700000000987654321, and if converted to int, or stringified via any method that doesn't use the repr, e.g. print, it displays as just 46700000000987654321.
I have a function that has the type Int -> Int -> Int -> Int. When i use div a b as a value for a variable in the function it seems, that the value gets rounded down to 0 if the return of div a b is 1/2 or anything double like.
Is this correct? Does Haskell cut of values like in java, if a double is forced into an integer?
div 1 2 doesn't return 0.5, which is then converted to the integer 0. It returns 0 in the first place. div performs integer division and as such always returns an integer (or other Integral type depending on which type you used it with). There's no doubles involved.
When you do convert a double to an integer, the method of rounding depends on which method you used. For example floor would round the number down whereas round would round to the nearest integer. There are no implicit conversions in Haskell, so any conversion will happen through a function.
Does Haskell cut off values like in java
no it does not.
When doing integer division, Java rounds towards zero, whereas Haskell rounds downwards; so in Haskell
\> (-9) `div` 10
-1
whereas in Java -9 / 10 is zero:
public class IntDiv{
public static void main(String []args){
double a = (-9) / 10;
System.out.printf("%.2f\n", a); // would print 0.00
}
}
How can I make that a float number only have 4 decimal places at most.
In my J2ME app I have two fields : unitPrice (4 decimal places) and quantity(3 decimal places) and when I multiply them I got number with more decimals than I need:
unitPrice :5.6538
quantity: 5
result: 28.269001
What can I do to have a result of only 4 decimals? and in general what do I need to do to use floats with a specific number of decimals.
Of course, if you were using Java SE the solution would be BigDecimal.
You could round as shown in the result initialization in the following program:
import java.math.BigDecimal;
public class Test {
public static void main(String args[]) {
float unitPrice = 5.6538f;
float quantity = 5;
float rawResult = quantity*unitPrice;
System.out.println(rawResult);
float result = Math.round(10000f*rawResult)/10000f;
System.out.println(result);
System.out.println(new BigDecimal(result));
}
}
The output is:
28.269001
28.269
28.2689990997314453125
Unfortunately, as shown by the final printout using BigDecimal, result is not really exactly 28.269. 28.269 is not exactly representable in any binary fraction format. That could affect future calculations if decimal fractions are really important.
As an alternative, consider doing everything in integers, with each type of data having an associated power-of-ten factor. For unit price, the factor would be 10,000. For quantity, it would be 1000.
For the product, you want it to be 10,000. The intermediate result of doing the multiplication will have a factor of 10^7, so divide by 1000 and round to an integer.
in vb6.0 we can use RonudOff() function for this operation;
example:
unitPrice :5.6538
quantity: 5
result: 28.269001
then " RounOff(result)" will give 28.2690;
i think their may be some similar function in java also
thanks
I want to code a function makeFraction :: Float -> Float -> (Int, Int) which returns (x,y) whenever I say makeFraction a b such that x/y is a proper fraction equivalent to a / b. For eg, makeFraction 17.69 5.51 should return (61,19).
I have a subroutine to calculate gcd of two numbers but my first task is to convert a and b to Int e.g. 17.69 and 5.51 should be converted into 1769 and 551.
Now I want to do it for numbers with arbitrary decimal places. Prelude function does not help me much. For instance, when I say toFraction(0.2); it returns 3602879701896397 % 18014398509481984 which would severely strain the correctness of my later computations.
Later I tried getting fractional values by using another library function properFraction(17.69) which suppose to give me only 0.69 but it produces 0.69000...013 which is not I would accept in a proper state of mind.
It does look like a problem arising from Floating point arithmatic. Till now I am not doing any data manipulation but only asking for the part of stored bits which I should be able to fetch from processor registers/memory location. Is there any special function library in Haskell to do such tasks?
PS: Seems like some useful tips are here How to parse a decimal fraction into Rational in Haskell? . But since I have typed so much, I would like to post it. At least the context is different here.
Yes, it is the limited precision of floating-point arithmetic you're encountering. The floating-point format cannot represent 0.2 exactly, so toFraction is actually giving you the exact rational value of the Float number you get when you ask for 0.2.
Similarly, 17.69 cannot be represented exactly, and because the point floats, its best representation has a larger absolute error than the error in the representation of 0.69. Thus, when you take away the integer part, the resulting bits are not the same as if you had asked to represent 0.69 as good as possible from the beginning, and this difference can be seen when the implementation prints out the result in decimal form.
It seems to me that instead of using a floating-point type like Float or Double, you should do all your computations using a type that can represent those numbers exactly, like Rational. For example,
(17.69 :: Rational) / (5.51 :: Rational)
evaluates to 61 % 19
As mentioned in the other answers, a Float cannot necessarily represent a given decimal number exactly. In particular, a Float is stored internally using the form a/(2^m). As a result, real numbers like 3/10 can only ever be approximated by floating point numbers.
But if a decent approximation is all you need, this might help:
import Data.Ratio
convertFloat :: Float -> Rational
convertFloat f = let
denom = 10^6
num = fromInteger denom * f
in round num % denom
For example:
> convertFloat 17.69
1769 % 100
> convertFloat 17.69 / convertFloat 5.51
61 % 19
Check out base's Numeric module, especially the floatToDigits function.
> floatToDigits 10 17.69
([1,7,6,9],2)
I am writing a function in which I need to read a string contains floating point number and turn it back to Rational. But When I do toRational (read input :: Double), it will not turn for eg: 0.9 into 9 % 10 as expected, but instead 81..... % 9007...
Thx
This is correct behavior. The number 0.9 is not representable as a Double, not in Haskell, C, or Java. This is because Double and Float use base 2: they can only represent a certain subset of the dyadic fractions exactly.
To get the behavior you want, import the Numeric module and use the readFloat function. The interface is fairly wonky (it uses the ReadS type), so you'll have to wrap it a little. Here's how you can use it:
import Numeric
myReadFloat :: String -> Rational -- type signature is necessary here
myReadFloat str =
case readFloat str of
((n, []):_) -> n
_ -> error "Invalid number"
And, the result:
> myReadFloat "0.9"
9 % 10
Binary floating point numbers cannot precisely represent all the numbers that base-10 can. The number you see as 0.9 is not precisely 0.9 but something very close to it. Never use floating-point types where decimal precision is needed — they just can't do it.