[C#] How can I speed up float truncation?

Started by
7 comments, last by Spa8nky 13 years, 3 months ago
I'm currently trying to truncate a float to a certain number of digits. I've come up with two methods:

1) Convert the float to a string and truncate that
2) Use the decimal.Round method

I've set up a test environment as follows:

        private void SpeedTest()        {            // [Method 1]            debugUtilities.StopwatchStart();            float value = 1.0023378734f;            for (int i = 0; i < 10000; ++i)            {                string truncated = StringTools.Truncate(value.ToString(), 4);            }            debugUtilities.StopwatchStop();            // [Method 2]            debugUtilities.StopwatchStart();            for (int i = 0; i < 10000; ++i)            {                float truncated = (float)decimal.Round((decimal)value, 4);            }            debugUtilities.StopwatchStop();        }


The ToString() method (method 1) is always faster.

How can I truncate a float faster (in a similar way to method 2) rather than using method 1?

It seems a little odd that converting it to a string is so much quicker.
Advertisement
float value = 1.0023378734f;int truValue = (int)(value + 0.0005)*10000;value = truValue/10000;



Give that a try. Did it quick so there might be a lil error in it.

theTroll
I've changed the method slightly to accommodate n decimal places:

            for (int i = 0; i < 10000; ++i)            {                //float truncated = (float)decimal.Round((decimal)value, 4);                float truncated = Truncate(value, 4);            }         private float Truncate(float value, int decimals)        {            float pow = 10;            decimals -= 1;            for (int i = 0; i < decimals; ++i)            {                pow *= 10;            }            int t = (int)(value * pow);            return t / pow;        }


It's a tiny bit faster but still not as fast as the string method.
These are also not correct. Try 12.345678 for example. The multiplier depends on where the decimal point is. Even the string truncation version does not take that into account, and is incorrect.
Is it truly necessary to truncate the numbers for your calculations?

Even a simple calculation like (int)(0.000101010f * 10000.0f) / 10000.0f can give you a result like "0.000099899898898," which is precisely not what you want.

Usually, truncation is done when you're outputting the number to the screen or a file; you don't force the float's value to conform to human readable standards, only the output.
- You don't include parsing the string back to a float in method 1, which will take up its fair share of time.
- Beware of potential behind-the-scenes caching mechanisms/optimizations. Use different values of each iteration and see if that makes a difference.
The truncation is there to shorten the length of the output before displaying on the screen. This means that the string will not be converted back to a float in method 1 but the float will need to be converted to a string in method 2. Apologies for not mentioning this sooner.

Quote:
These are also not correct. Try 12.345678 for example. The multiplier depends on where the decimal point is. Even the string truncation version does not take that into account, and is incorrect.


That is true but it is a string that will be displayed so it will need to be of a certain length. What improvements would you suggest?
string s = string.Format("{0:0.0000}", number);


This will be fast enough until it becomes a bottleneck. If this output will be used for rendering on screen, then emitting single glyph of resulting string will take much more time than formatting itself.
Thanks Antheus.

Is there any way I can use your method to limit the number of digits it displays (significant figures)?

E.g.

48003.0032 (5 s.f.) would display 48003

48.0030032 would display 48.003

EDIT:

Never mind, I've got it:

string truncated = string.Format("{0:G5}", value);


Thanks again.

This topic is closed to new replies.

Advertisement