Git Product home page Git Product logo

Comments (19)

eweitnauer avatar eweitnauer commented on August 24, 2024 1

So my idea was to run something like this piece of code

rationalize_real = function(num) {
  if (Math.round(num) === num) return num;
  var parts = num.toString().split('.');
  return '(' + (parts[0]==='0' ? parts[1] : parts[0]+parts[1]) + '/1'
             + Array(parts[1].length+1).join('0') + ')';
}

to replace each number in the input by a rational to avoid any floating point operations in Algebrite. It would not change 1/3, since only the 1 and the 3 would be passed to the function, but it would turn 0.5 into 5/10 and 3.3333 into 33333/10000.

What is the more general case you mentioned?
Where should I best add the test cases?

from algebrite.

davidedc avatar davidedc commented on August 24, 2024

I'll look into the ReferenceError: Eval_display is not defined problem.

In regards to getting text out of an Algebrite expression: .toString() should do the job.

In regards to checking equivalences, here are some starting points:

Algebrite.equal(Algebrite.eval('x+x+x'),Algebrite.eval('3*x')); // 1
Algebrite.equal(Algebrite.eval('x+x+x+1'),Algebrite.eval('3*x')); // 0

Algebrite.eval('x+x+x == 3*x').toString(); // "1"
Algebrite.eval('x+x+x > 3*x').toString(); // "0"
Algebrite.eval('x+x+x + 1 > 3*x').toString(); // "1"

Note that indeed it's best, for more complex simplifications, to unleash "simplify" on both sides, otherwise for example this equivalence is not found:

Algebrite.equal(Algebrite.simplify('cos(x)^2 + sin(x)^2'),Algebrite.simplify('1')); // 1, not found without simplify

P.S.
Just to manage your expectations to determine equivalences: to do that in general is too much of a complex job for any CASs, so your mileage may vary.

P.P.S. longer version
...there can be many forms to an expression, finding a canonical form is not always possible or practical, and CASs can't practically try them all. Many equivalences (e.g. some famous ones are Ramanujan formulas who could draw amazing equivalences without always being sure of correctness or proof) took many years of mathematician's acumen to demonstrate (and development of new algorithms to be able to be handled by CASs, again related to Ramanujan see equivalences of nested radicals where a general algorithm was only found in 1989 by Susan Landau https://en.wikipedia.org/wiki/Nested_radical#Landau.27s_algorithm )

from algebrite.

davidedc avatar davidedc commented on August 24, 2024

I see now your work on https://graspablemath.com/ , I'd have been less verbose if I knew you are in the field :-)

Yes please if you find other cases you'd expect to work please let me know...

from algebrite.

eweitnauer avatar eweitnauer commented on August 24, 2024

Thank you for explaining!

I ended up using Algebrite.equal(Algebrite.simplify(expr1), Algebrite.simplify(expr2)), which works great for the cases I'm concerned about!

For all cases, except... When I am comparing (1+1)^(1/3) and (0.5*4)^(1/3), Algebrite tells me they are different. The reason is that (1+1)^(1/3) simplifies to 2^(1/3), while (0.5*4)^(1/3) simplifies to 1.25992. Is there a straightforward solution to this? Maybe a way to disable simplifications that lose precision? Or casting real numbers back into integers?

from algebrite.

davidedc avatar davidedc commented on August 24, 2024

Using a float anywhere in an expression (0.5 in your example) makes the system calculate the approximate values.

You could:

  1. behind the scenes also force both sides to a float with "float" and check that the difference between them is really small.
  2. OR, more clean, we could add a way to have Algebrite to parse the floats in an expression and transform them into rationals in some circumstances (maybe a flag, or a "toRational" function or similar). But that float -> rationals mechanism would have to be implemented...

from algebrite.

eweitnauer avatar eweitnauer commented on August 24, 2024

Brilliant! Turning the floats into rationals as a first step will work perfectly! Something very naive like turning floats into (n*10^k)/(10^k) will probably work fine. I'll do that on my side. Let me know if you want to integrate something like this into Algebrite.

from algebrite.

davidedc avatar davidedc commented on August 24, 2024

yes slightly byzantine though that it would work on 1/2 but not on 1/3 etc... You sure that you'll be working only with floats that will work? Would you consider doing the more general case (or are you in a pinch)?

On a separate note, It'd be safer to cover your use cases with tests so that I'm sure I'm not going to break them with coming versions... I.e. if you add them you'll be covered.

from algebrite.

davidedc avatar davidedc commented on August 24, 2024

handling the general case would mean introducing a notation for infinite digit sequences like 0.33333... (but sequences can be slightly more complex so might need to get more creative than just using the three dots ) and implementing the algorithm that finds out which rational creates the sequence. I can't link to it easily from iPhone but it should be rather compact.

...tests are in the test folder, try to see if there is a test file that fits the type of work you do.

from algebrite.

davidedc avatar davidedc commented on August 24, 2024

links for converting floats to rationals: https://rosettacode.org/wiki/Convert_decimal_number_to_rational and http://stackoverflow.com/questions/95727/how-to-convert-floats-to-human-readable-fractions

from algebrite.

eweitnauer avatar eweitnauer commented on August 24, 2024

The rosettacode link does not work for me, but the algorithm in the accepted answer from stackoverflow is neat!

What is the use case for this for an Algebrite user? I personally just needed a way to force exact integer-based calculations for initial expressions that contained floats. So in a way limiting the size of the denominator to make it more human-readable is exactly what I don't want :)

Is there a scenario where a user would actually want nice looking fraction approximations instead of real numbers or ugly fractions? I guess I can see it being useful in combination with some special notation to mark repeating sequences in the digits so the conversion between real notation and fraction notation is lossless. That's not part of the existing algorithm, though.

from algebrite.

davidedc avatar davidedc commented on August 24, 2024

With some euristics I think one can guess most human-entered floats of the type you seem to get as input.

I think it's intereating to have. Ideally I'll want to make an inverse symbolic calculator but one step at a time...

Maybe if you can tell what you expect people to present as input in your cases, I'm going to use that to do the euristics.

The problem with the special notation for the exact representation is that a) floats don't have that notation and b) can we expect users who can't be bothered to input the rational in the first place to then use the special notation of the exact decimal expansion?

from algebrite.

davidedc avatar davidedc commented on August 24, 2024

so, to the point, the use case for this is to straighten "lazily"-entered floats into guessed rationals. 0.5 to 1/2 but also 0.33333 to 1/3. So in other words it guesses normal textbook fractions, nothing too convoluted.

from algebrite.

davidedc avatar davidedc commented on August 24, 2024

so the name of the function could be, aptly, something like "guessSimpleFraction" . It's a convenience for input, nothing more.

from algebrite.

murkle avatar murkle commented on August 24, 2024

There's a nice algorithm here by John Kennedy to convert double -> rational
https://github.com/geogebra/geogebra/blob/master/common/src/main/java/org/geogebra/common/kernel/algos/AlgoFractionText.java

If you also want to convert double -> surd then you can use the PSLQ algorithm, eg
https://github.com/geogebra/geogebra/blob/master/common/src/main/java/org/geogebra/common/kernel/cas/AlgoSurdText.java

from algebrite.

murkle avatar murkle commented on August 24, 2024

Just realised I've written a JavaScript version which you're welcome to use under MIT licence

`
DecimalToFraction: method(function(decimal, AccuracyFactor) {
var FractionNumerator, FractionDenominator;
var DecimalSign;
var Z;
var PreviousDenominator;
var ScratchValue;

        var ret = [0,0];
        if (isNaN(decimal)) return ret; // return 0/0 

        if (decimal === Infinity) {
            ret[0] = 1;
            ret[1] = 0 ; // 1/0
            return ret;
        }
        if (decimal === -Infinity) {
            ret[0] = -1;
            ret[1] = 0; // -1/0
            return ret;
        }

        if (decimal < 0.0) DecimalSign = -1.0; else DecimalSign = 1.0;

        decimal = Math.abs(decimal);

        if (Math.abs(decimal - Math.floor(decimal)) < AccuracyFactor) { // handles exact integers including 0 
            FractionNumerator = decimal * DecimalSign;
            FractionDenominator = 1.0;

            ret[0] = FractionNumerator;
            ret[1] = FractionDenominator;
            return ret;
        }
        if (decimal < 1.0E-19) { // X = 0 already taken care of 
            FractionNumerator = DecimalSign;
            FractionDenominator = 9999999999999999999.0;

            ret[0] = FractionNumerator;
            ret[1] = FractionDenominator;
            return ret;
        }
        if (decimal > 1.0E19) {
            FractionNumerator = 9999999999999999999.0 * DecimalSign;
            FractionDenominator = 1.0;

            ret[0] = FractionNumerator;
            ret[1] = FractionDenominator;
            return ret;
        }

        Z = decimal;
        PreviousDenominator = 0.0;
        FractionDenominator = 1.0;
        do {
            Z = 1.0/(Z - Math.floor(Z));
            ScratchValue = FractionDenominator;
            FractionDenominator = FractionDenominator * Math.floor(Z) + PreviousDenominator;
            PreviousDenominator = ScratchValue;
            FractionNumerator = Math.floor(decimal * FractionDenominator + 0.5); // Rounding Function
        } while ( Math.abs((decimal - (FractionNumerator /FractionDenominator))) > AccuracyFactor && Z !== Math.floor(Z));
        FractionNumerator = DecimalSign*FractionNumerator;

        ret[0] = FractionNumerator;
        ret[1] = FractionDenominator;
        return ret;
    })

`

from algebrite.

murkle avatar murkle commented on August 24, 2024

https://web.archive.org/web/20111027100847/http://homepage.smc.edu/kennedy_john/DEC2FRAC.PDF

from algebrite.

davidedc avatar davidedc commented on August 24, 2024

thanks a lot! First shot at this: 11013a3 . I'm going to credit John Kennedy immediately in the next commit.

from algebrite.

davidedc avatar davidedc commented on August 24, 2024

credited

from algebrite.

davidedc avatar davidedc commented on August 24, 2024

approxratio now works on entire expressions:
https://github.com/davidedc/Algebrite/blob/eb1ed2e6a3720435f60ad88100329d58b733b88f/tests/approxratio.coffee . So this should cater for typical ratios entered as floats. Hopefully most people would still enter irrational and transcendental numbers with an appropriate expression rather than as a float. Those other cases to be picked up later.

from algebrite.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.