Welcome to the Onshape forum! Ask questions and join in the discussions about everything Onshape.

First time visiting? Here are some places to start:
  1. Looking for a certain topic? Check out the categories filter or use Search (upper right).
  2. Need support? Ask a question to our Community Support category.
  3. Please submit support tickets for bugs but you can request improvements in the Product Feedback category.
  4. Be respectful, on topic and if you see a problem, Flag it.

If you would like to contact our Community Manager personally, feel free to send a private message or an email.

Anyone have an FS that can convert a decimal length to a (reduced) fractional equivalent

eric_pestyeric_pesty Member Posts: 2,400 PRO

I know people in the metric (most of) world are going to be like "huh?" but I'm trying to match a convention to build a part description parametrically…

I was hoping Pascoe's "variable to string" FS would do it but it doesn't include that function, which tells me it's not super trivial so I thought I would ask if anyone has some code I can (respectfully!) "steal" before I go on a coding adventure!

Comments

  • Caden_ArmstrongCaden_Armstrong Member Posts: 334 PRO

    The stack overflow thread on the topic is somewhat helpful resource if you want an "optimal" answer
    https://stackoverflow.com/questions/5124743/algorithm-for-simplifying-decimal-to-fractions

    Its not a trivial problem, but its a simpler problem if you are constrained to not just any fractions, but typical base 2 fractions ( 1/4, 1/8, 1/16 , etc)

    You could find the closest /32 fraction (or 64 or 128) and then find the highest common factor


    for (var i = 0; i < 101; i += 1) { var dec = i/50; var denom = 32; var modval = 1/32; var numer = round(dec/modval); // this is the numerator in a x/32 var factors = [2,4,8,16,32]; // find the equivalent fraction with a different base for (var factor in factors) { if(numer%factor == 0) { println( numer/factor ~"/"~(32/factor)); // the last option this produces is the best answer } } }
    www.smartbenchsoftware.com --- fs.place --- Renaissance
    Custom FeatureScript and Onshape Integrated Applications
  • eric_pestyeric_pesty Member Posts: 2,400 PRO

    Thanks @Caden_Armstrong ,

    Ended up writing something with some help from ChatGPT (for the algorithm part)…

    Seems to work and looks like this if anyone is wondering:

    FeatureScript 2780;
    import(path : "onshape/std/common.fs", version : "2780.0");
    
    annotation { "Feature Type Name" : "Decimal to Fraction", "Feature Type Description" : "Convert a decimal length to a fraction string" }
    export const DectoFrac = defineFeature(function(context is Context, id is Id, definition is map)
        precondition
        {
            annotation { "Name" : "Decimal Length" }
            isLength(definition.decLength, LENGTH_BOUNDS);
            
            annotation { "Name" : "Smallerst Denom, eg: 16 for 1/16", "UIHint" : UIHint.REMEMBER_PREVIOUS_VALUE }
            isInteger(definition.precision, POSITIVE_COUNT_BOUNDS);
            annotation { "Name" : "Variable Name" }
            definition.varName is string;
            
                
        }
        {
            const decValue = definition.decLength/inch;
            const precision = definition.precision;
            var whole=floor(decValue);
            var frac = decValue - whole;
            
            var denominator= precision;
            var numerator = round(frac * denominator);
            
            println(whole~" "~numerator~" / "~denominator);
            
                
            if (numerator !=0)
            {
                var a=numerator;
                var b=denominator;
                var r=1;
                while (b!=0)
                {
                    r=a%b;
                    a=b;
                    b=r;
                }
                var GCD=a; 
                println(GCD);
                numerator= floor(numerator/GCD);
                denominator = floor (denominator/GCD);
                
            }
            else
            {
                denominator=1;
            }
            
            if (numerator==denominator)
            {
                
            whole += 1;
            numerator=0;
                
            }
            
            /*
            println(whole);
            println(numerator);
            println(denominator);
            */
            var theString;
            if (whole==0)
            {
             theString=numerator~"/"~denominator;
            }
            else
            {
                theString=whole~"-"~numerator~"/"~denominator;
            }
            
            setVariable(context, definition.varName, theString);
            
            // Define the function's action
        });
    
  • jnewthjnewth Member, OS Professional Posts: 75 PRO

    I have seen clever people use clever ways to do this. I thought to myself "….I do not trust math. Nor cleverness. Nor software, come to think of it."

    I present to you: A lookup table.

    You can use the feature or you can call the exported function convertToFraction from your own code. You can specify the output format by "precision" or 1/16, 1/32, and 1/64 increments. It finds the closest match. An output of "precision 1" returns a fractional representation that fits in X/Y. A "precision 2" returns XX/YY, etc.

    A concrete example:

    input: .04

    output as nearest 1/16: 1/16 (.0625 is closer to .04 than 0)

    output as nearest 1/32: 1/32 (.03125 is closer to .04 than 0)

    output as nearest 1/64: 3/64 (.046…)

    output as precision 1: 0 (0 is closer than 1/9)

    output as precision 2: 1/25

    output as precision 3: 1/25 (.04 is exactly 1/25)

    output as precision 4: 1/25 (.04 is exactly 1/25)

    Greenshot 2025-10-28 13.35.02.png

    Thanks to my former co-conspiratorllaborator at Onshape, the inestimable @Lindsay_Early for help with this.

    If you find any problems or errors with it, let me know. Hope it helps!

    https://cad.onshape.com/documents/5298c06ac953e3d41305f9b8/w/4c86b4c728c75b0abe3ab25d/e/97b8534fe1c74a16ffd44cd0

Sign In or Register to comment.