December 27, 2017

Dynamo: Forcing Exactly One-Half to Round Up

In the same Dynamo graph on which my previous post was based, I had a need to round a real number to the nearest whole number, and I wanted a decimal of exactly .5 to round up. The Math.Round node met all my rounding needs except for when the decimal value is exactly 0.5; that node "rounds to even," which means that both 1.5 and 2.5 will round to 2, since 2 is even. Statistically, when dealing with a large amount of data, always rounding exactly 0.5 to even (or rounding always to odd) makes sense, as always rounding up would tend to skew any mathematical analysis of the data to a higher value. In this case, the number was being used only as a label, and I decided that it should always round up.

I put together the following nodes to achieve the desired results. Numbers in the explanation below refer to the numbers in the image. As always, you can click on the image to see the full-size version.

  1. This code block provides the source number to be processed.
  2. The nodes in Area 2 divide the source number by 100. In the example in the image, this results in a value of 12.5. This value is fed to the nodes in Areas 3, 4 and 5.
  3. The Math.Floor node truncates any fractional part in the value from Area 2, resulting in an integer of 12 in the example. This value is fed to the nodes in Areas 5 and 6.
  4. The Math.Round node takes the value from Area 2 and rounds it. For the example value of 12.5, the .5 is rounded to even, or 12. The result is a floating point number. This value is fed to a node in Area 7.
  5. The nodes in Area 5 take the value from Area 2 (12.5 in the example) and Area 3 (12 in the example) and subtract the Area 3 value from the Area 2 value. The result of the subtraction (0.5 in the example) is compared to the value in the Code Block, which is 0.5, by the == node. If the two are equal, the result of the comparison is true, as it is in the example; otherwise, it is false. This result is fed to the test input of the If node in Area 8.
  6. The Area 6 nodes take the integer result from Area 3 and add the value in the Code Block, or 1.0, to it. This is the rounded up value; it is 13 in the example.
  7. The two Math.Floor nodes in Area 7 take the real number results from Areas 4 and 7 and convert them to integers. These values were already whole numbers, but the Math.Round and + nodes output is a floating point number, not an integer. The application for which this rounding is being done required an integer. If it does not matter to your application whether the rounded number is a floating point number or an integer, these nodes would not be required. In hindsight, it occurs to me that one Math.Floor node could have been placed after the If node.
  8. The If node in Area 8 determines whether to use the result of the nodes in Areas 4 - 7 or Areas 3 - 6 - 7, based on whether Area 5 evalutes to true or false. If true, then the fractional part was exactly 0.5, and the rounded up value from Areas 3 - 6 - 7 is used. Otherwise, the rounded value from Areas 4 - 7 is used. This value will be rounded up for fractional values greater than 0.5 and down for fractional values less than 0.5.

No comments: