tompazourek / rationals Goto Github PK
View Code? Open in Web Editor NEWπ Implementation of rational number arithmetic for .NET with arbitrary precision.
License: MIT License
π Implementation of rational number arithmetic for .NET with arbitrary precision.
License: MIT License
The default value is both IsZero
and IsOne
at the same time and equals to any Rational
value.
Rational weird = default(Rational); // new Rational();
Console.WriteLine($"{weird}.IsZero : {weird.IsZero}"); // True
Console.WriteLine($"{weird}.IsOne : {weird.IsOne}"); // True
Console.WriteLine($"{weird} == 10 : {weird == 10}"); // True
Console.WriteLine($"10 == {weird} : {10 == weird}"); // True
Maybe it's worth to consider (0/0)
form as NaN
? Or at least make it behave as Zero
(i.e. (0/1)
) consistently.
For Example:
Best Ask: 0.0001717, Best Bid 0.0001715
Best Ask: 1717/10000000, Best Bid 343/2000000
Best Ask: 0.000172, Best Bid 0.000172
generated by:
let bestAsk = last10Asks |> Array.last
let bestAskD = Rational.ParseDecimal (bestAsk, tolerance = 0.000000000001m)
let bestBid = first10Bids.[0]
let bestBidD = Rational.ParseDecimal (bestBid, tolerance = 0.000000000001m)
printfn "\nBest Ask: %s, Best Bid %s" (bestAsk) (bestBid)
printfn "\nBest Ask: %A, Best Bid %A" (bestAskD) (bestBidD)
printfn "\nBest Ask: %f, Best Bid %f" ((decimal) bestAskD) ((decimal) bestBidD)
There just looks like there is a bit of implicit rounding happening here. :-\
Since all of these have only limited precision, it might be hard to get the right result.
E.g. number 0.33333333
will not get parsed as 1/3
, which might be expected.
For this, maybe there could be a method, which will accept a certain tolerance coefficient. Then we can find the closest rational number approximation thanks to continued fraction expansions.
Related: #7
The very example provided on the front page doesn't parse with this library:
var p2 = Rational.Parse("1 2/5"); // 7/5
((double)Rational.Pow((Rational)0.95, 734)) != Math.Pow(0.95, 734)
Specifically, ((double)Rational.Pow((Rational)0.95, 734) == 4.4578585297200003E-17, while Math.Pow(0.95, 734) ==4.4578585297232747E-17. Wolfram Alpha agrees with Math.Pow, so I'm assuming that it is correct.
I suspect that the (double) conversion logic is converting to a decimal, then converting that to a double, because if you cast both to the decimal (instead of double) they do produce the same result.
Upon further examination, yeah, it looks like it is converting to decimal, then to double -- if you try to convert a small value into a double (which can handle smaller numbers than a decimal can), the underflow exception complain that "Value was either too large or too small for a Decimal." rather than the expected double.
Very odd problem -- I'd have assumed that decimal always has more significant digits than double, but apparently not (!?)
CanonicalRational always keeps canonical form, after every operation.
Actual: 3 > (-4)/(-1)
Expected: 3 < (-4)/(-1)
Addition gives a false result
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Rationals;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Rational left = (Rational)1 / 2;
Rational right = (Rational)1 / 4;
Rational sum = left + right; // equals to: 3 / 4
Console.WriteLine(sum);
Console.ReadKey();
}
}
}
Return result 6/8, but should be3/4
version 2.1.0
var p = (Rational) 1000;
int magnitude = p.Magnitude; // 2οΌit should be 3
source code
public int Magnitude
{
get
{
if (IsZero)
return 0;
var numLog = BigInteger.Log10(BigInteger.Abs(Numerator));//Numerator is 1000,numLog is 2.9999999...
var denLog = BigInteger.Log10(BigInteger.Abs(Denominator));
return (int)Math.Floor(numLog - denLog);
}
}
and my temp code
static int GetNumCount(BigInteger integer)
{
integer = BigInteger.Abs(integer);
var count = 0;
while (integer > 0)
{
count++;
integer /= 10;
}
return count;
}
static int Magnitude(Rational r)
{
if (r.IsZero)
return 0;
var numeratorNumCount = GetNumCount(r.Numerator);
var denominatorNumCount = GetNumCount(r.Denominator);
var numeratorAbs = BigInteger.Abs(r.Numerator);
var denominatorAbs = BigInteger.Abs(r.Denominator);
var c = BigInteger.Pow(10, Math.Abs(numeratorNumCount - denominatorNumCount));
if (numeratorNumCount > denominatorNumCount)
denominatorAbs *= c;
if (numeratorNumCount < denominatorNumCount)
numeratorAbs *= c;
if (numeratorAbs >= denominatorAbs)
return numeratorNumCount - denominatorNumCount;
else
return numeratorNumCount - denominatorNumCount - 1;
}
A tuple deconstructor could allow deconstructing rational number into a tuple of numerator and denominator.
Rational created with negative numerator and denominator gives 0 when casting to decimal. Isn't it a bug?
var num = new Rational(-9, -3);
var dec = (decimal) num; // dec is 0
I found it trivial to add the ability to simplify Rationals for a project I'm working on, so figured I'd contribute it upstream. I'll be submitting a PR for this shortly, but tracking it as an issue for posterity.
Would like an instance method Simplify()
on Rational
that computes the greatest common divisor of the numerator and denominator, and then if that gcd is != 1, divides both the numerator and denominator by the gcd and returns a new rational, otherwise returns itself (as already simplified).
Example:
var r = new Rational(14, 26);
var s = r.Simplify(); // returns 7/13
Personally, I like this being an instance method as it feels natural in usage, but if you would prefer to make it a static method instead I would not be opposed to changing my PR. Thanks for this great library!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.