Best way to trim trailing zeros?

So I want to replace "31.100" for "31.1" and "31.000" to "31" and I couldn't find any buitin function to do one so I ended up with this. Do you have a better one?

function stripTrailingZeros(value) {
    if (value instanceof Lang.String) {
		if (value.find(".") != null) { // Only mathers if we contain a decimal
			var carray = value.toCharArray();
			var i = carray.size() - 1;
			for (; i > 0; i--) {
				if (carray[i].equals('.')) { // If we reached the '.', we'll skip it too and stop so we don't drop zeros before '.'
					i--;
					break;
				}
				if (carray[i].equals('0')) { // Trailing zero? Keep going
					continue;
				}

				break; // Not one of the above, so that's where we stop
			}
			value = "";
			for (var j = 0; j <= i; j++) {
				value += carray[j];
			}
		}
	}
	return value;
}

Top Replies

  • Maybe worth to read about the formats and play a bit with it, there might be a modifier that would do almost what you want, and if you're lucky with that, then all you're left to do is to…

All Replies

  • That is a good way to do it if the value is a string from user input and not a numeric type. Although it may be slightly faster if:

    - you do not create a new string by appending one character at a time.

    - you do not use String.find() (in the worst case, String.find() has to scan the entire string anyway, so you may as well skip it.

    If the value is numeric, then converting it to a string will ofc have the potential to introduce error (due to floating point issues and the particular implementation of toString() / format()). It might be better to work on the numerical value before conversion to string, although ofc there will be still be floating point issues.

    EDIT: removed bad code

    - it was based on getting the number of decimal places, then rounding to a certain number of places. Both of these are subject to floating point error ofc

  • Thanks. I didn't think about using substring. That code though wouldn't work if the string only has "31" has there are no dots and would therefore return "3". 

    I'm not really concerned with the other types as it's use only in this way:

    $.stripTrailingZeros((discharge).format("%0.2f"))

  • Maybe worth to read about the formats and play a bit with it, there might be a modifier that would do almost what you want, and if you're lucky with that, then all you're left to do is to remove ".0" at the end of the string.

  • Oops my bad. Yeah, it's probably easier just to check if there's a decimal point before scanning the string.

    After all, performance is probably not a concern here. 

  • Maybe worth to read about the formats and play a bit with it, there might be a modifier that would do almost what you want, and if you're lucky with that, then all you're left to do is to remove ".0" at the end of the string.

    I don't understand this comment. Removing trailing 0s at the end of a numeric string (to the right of the decimal point) is already what he is trying to do.

    What conceivable printf-style format would help him accomplish this goal, while not actually removing the trailing 0s? (It's a moot point since there's no format which could either do part or all of task of removing trailing 0s. Keep in mind that floating numbers themselves don't actually have trailing zeroes to the right of the decimal place, trailing 0s are just part of the conversion to string. And I think we know that there's no printf-style format string which is supposed to "print a number without trailing 0s", otherwise we wouldn't be having this discussion in the first place.)

    I'm not really concerned with the other types as it's use only in this way:

    $.stripTrailingZeros((discharge).format("%0.2f"))

    Yeah, the generic solutions are meant to handle an arbitrary number of decimals. For your use case, where you are going to display a limited number of decimals to the user anyway, your code is probably just fine.

  • Yeah, only two fields every 5 seconds at most. Not worth the trouble.

  • It's working well. I went a bit further and now in some occasion, before calling this function, I dynamically limit the number of decimals that should be displayed using this code snippet

    PS. This site sucks when trying to include code. Most of the time, I get a 'You've been blocked' (scared me the first time I got that!) or an error if I try to include the code as text.

  • Sorry, I'm unable to post 3 lines of code or even uploading a screenshot with the fixed code...

  • As per the comment above yours, SylvainGa is dynamically rounding to 0 to 3 decimals - before removing trailing 0s - based on the number of sig figs in the value. I think your answer only works with up to 2 decimals.

    Your answer does suggest a simple generic solution that avoids the floating point errors in my previous solution [*]:

    https://pastebin.com/zGSgmiXz 

    [*] the previous solution had other problems, but even if those were fixed, it would still have inherent floating point errors

    The final test case - toStringWithoutTrailingDecimals(100.5999, 3) - demonstrates that the value is correctly rounded to the given precision / max number of decimals before determining the number of decimals. if it wasn't, then there would be a conflict with "%.xf", which does round to specified number of decimal places

    e.g. without Math.round in the code, toStringWithoutTrailingDecimals(100.5999, 3) would incorrectly be displayed as "100.600"

    In the above code snippet, "maxDecimals" also refers to the number of decimals of precision that are assumed in the input. Maybe it should have been called "precision" instead.

    As per the previous discussion, the snippet is fine for displaying numbers (and not necessarily for using them in intermediate calculations)

    One problem with this approach is it doesn't work numbers greater than 2 ^ 32 - 1 / 10 ^ precision, which is hopefully not an issue here. (It could be if you started using it with precision / maxDecimals greater than 3 though.) To mitigate this, the following change could be made:

    Original code:

    num = Math.round[num * factor].toNumber[];

    New code:

    num = Math.round[num * factor].toLong[];

    In practice it might not be realistic because you'd barely be able to display such numbers on a small watch screen in a user-friendly way.

    This site sucks

    Yes, yes it does.