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.

toString incosistent behavior

martin_korinekmartin_korinek Member Posts: 5

Hello all,

I would like to ask for help.

The text function toString(#variable/mm) will convert 37mm to 37, but same time converts 36 mm to 36.00000…1. This drive me really mad.

Is there some reasonable way how to control number of decilmals places?

I appreciate any help.

Thanks

toString.png

Answers

  • _anton_anton Member, Onshape Employees Posts: 444

    Everything is stored internally in meters, so 36 mm is actually 36 * 0.001 m. Which results in floating-point artifacts.

    Use roundToPrecision: https://cad.onshape.com/FsDoc/library.html#roundToPrecision-number-number

  • martin_korinekmartin_korinek Member Posts: 5

    Thank you for suggested solution!
    But the explanation does not make sense to me:
    36 x 0,001 is NOT 36,000000000000001 (see screenshot)
    same time
    37x0,001 is NOT 37 (see screenshot)

  • _anton_anton Member, Onshape Employees Posts: 444

    It's not obvious off the top of my head why you're seeing these specific numbers (there might be some additional unit conversion in the middle somewhere), but it's generally true that not all numbers can be represented exactly in floating-point math; for some, we can only get close. For example, 0.1 + 0.2 = 0.30000000000000004. If you're formatting numbers for display, you should assume that you'll get artifacts like this, and round appropriately.

  • martin_korinekmartin_korinek Member Posts: 5

    Thanks for the help. I did encounter another issue with this.

    toString(roundToPrecision(34.5,1)) will produce string "34.5" which is expected and wanted.

    toString(roundToPrecision(35,1)) will produce string "35" instead of "35.0".

    Can someone please suggest what trick do I need to use to archive that string made from number will have fix number of decimals?

  • MichaelPascoeMichaelPascoe Member Posts: 2,306 PRO
    edited April 30

    If your certain there are no decimals at all, you can intentionally add a really small and unique value after the rounding, like 0.019191, convert it to string, then remove the unique string.

    replace(toString(roundedValue + 0.019191), "19191", "")
    

    Also, this might save you some time, try the Variable to String custom feature.
    It will convert your variable with units to a string, while keeping in mind the expected units and trailing zeros.

    image.png

    The variable to string feature uses a more robust way to check for zeros. It splits the string into an array by checking if there is a decimal. If there is a decimal, splits the value to the right of the decimal into another array and counts the values. From there, it checks if there are too few decimals then adds accordingly:

        var roundedValue = roundToPrecision(value.value * conversionMultiplier, roundingPrecision);
    
        if (enforceTrailingZeros)
        {
            var notEnoughDecimals = false;
            var qtyTrailing = 0;
            var s = toString(roundedValue);
            s = splitByRegexp(s, "[.]");
    
            try silent
            {
                notEnoughDecimals = size(s) < 2;
                qtyTrailing = 0;
            }
    
            try silent
            {
                qtyTrailing = size(splitIntoCharacters(s[1]));
                notEnoughDecimals = qtyTrailing < trailingZeros;
            }
    
            if (notEnoughDecimals)
            {
                const zerosToAdd = trailingZeros - qtyTrailing;
                const zeroArray = makeArray(zerosToAdd, "0");
                var toAdd = "";
    
                for (var i = 0; i < size(zeroArray); i += 1)
                {
                    toAdd ~= zeroArray[i];
                }
    
                try silent
                {
                    toAdd = s[1] ~ toAdd;
                }
    
                roundedValue = s[0] ~ "." ~ toAdd;
            }
        }
    
        return roundedValue ~ unitLabel;
    

    Learn more about the Gospel of Christ  ( Here )

    CADSharp  -  We make custom features and integrated Onshape apps!   Learn How to FeatureScript Here 🔴
Sign In or Register to comment.