How can I change the precision of double value in Haskell? - haskell

I would like to change the precision of double value.
For example:
I need to get 3.14 from 3.141592653589793
I expect function like:
scale :: Int -> Double -> Double
> scale 2 3.141592653589793
3.14
> scale 3 3.141592653589793
3.141
Also, I would like to be able to choose the rounding strategy.
round :: ROUND -> Int -> Double -> Double
> round ROUNDUP 5 3.141592653589793
3.1416
How can I do it?
How can I apply the rounding strategy for it?
P.S.:
Expected behavior in Java should setScale of BigDecimal: https://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html

The correct Haskell analog of Java's BigDecimal is Fixed, not Double. You may convert between different precisions via realToFrac.

Related

How can I prevent Python from automatically converting int to float when I use pow and mod?

I am trying to encrypt with rsa using the formula c = m^p mod q.
The Problem is if the number is too large, python3 convert it to float when doing modulo.
I tried to stop converting by converting into int
c = int(int((pow(n,p)) % q))
the problem is when p is too big it automatically has decimals and python thinks , that i am trying integer to float. Which leads to this:
OverflowError: int too large to convert to float
Is there a way to solve this ?
This may not solve your problem, but it does address the specific concerns you put forth in your question and suggests possible causes based on what you've told us.
The problem you're having isn't with %. As per the documentation,
The floor division and modulo operators are connected by the following identity: x == (x//y)*y + (x%y).
Given integer x and y, (x//y)*y is always an exact integer, so x - (x//y)*y == x%y must also be an integer.
Since you said you are using the built-in pow function, I suspect that your problem is that your inputs are floats instead of ints. In that case, both pow and ** will try to convert the other of the argument to float, which could be the source of your error. If this is the case, wrapping each argument in int will make the error go away, but your RSA implementation will be incorrect.

Groovy - confusion double vs float

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.

Does Haskell do a default conversion from double to integer?

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
}
}

While computing proper fraction in Haskell

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)

problem with Double and Rational Number

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.

Resources