Rounding with RobotMesh Python on V5 brain


#1

Hi, how do I display a rounded float on the V5 brain with RMS Python? Tried this simple code and it displays 0.949999. I want it to display 0.95. Thanks!

PS. Sorry for being a complete idiot, I can’t find the “embed code” button/icon/option in the new forum interface.

# VEX V5 Python Project
import sys
import vex

#region config
brain = vex.Brain()
#endregion config

some_variable = 0.95
brain.screen.print_at(230, 125, True, str(round(some_variable,2)))


#2

RMS uses the standard Python math library as a reference, you can see the API documentation here.

You’d use math.ceil() or math.floor() to round your float to the nearest integer.


#3

@WillRobinson:

math.ceil() returns 1.0
math.floor() returns 0.0
I wanted to print 0.95
Thanks


#4

RMS seems to use Python 2.6, so you should be able to use

brain.screen.print_at(230, 125, True, '{0:1.2f}'.format(my_float))

The curly braces note a format expression. The0 refers to the zeroth argument passed to the format function (you can do as many as you want), and the 1.2 before the f format specifier is used to specify the precision of the number being displayed.

For more information, see this section of the Python docs (and the one below it has some more examples).


#5

Ah, apologies, I skimmed.

You’re right, round() is the function you’re looking for in RMS Python.

What @hotel mentioned above should work. If not, try performing the round() and string conversion in a separate variable assignment statement, then pass that variable in to the print_at() function.

Might be some funny business going on in there with order of operation.


#6

@hotel:
format did not work (unless Pymite/RMS needs some other syntax or something) - gave syntax error.

@WillRobinson:
tried round() as a separate variable, tried to pass it as different things to print_at(), just does not work.

I ended up multiplying by 100 and adding the 1 to round, then building a string out of pieces. It sure works, but it’s ghetto (and definitely not conducive to learning efficient programming and to focusing on the robot).

I just wish the API docs were clear on what works and what does not, on proper syntax and some simple examples would be good (not complaining at all, love RMS, just a constructive thought).


#7

I messed around with this tonight - I think it’s the old Python 2.x problem with representing floating point precision in binary. There’s a Decimal library that solves it, but we can’t include random libraries in RMS.

A possible compromise is to convert it to a string and just print off the string to the number of characters that corresponds to the decimal length you want:

some_variable = 0.95
brain.screen.print_at(230, 125, True, str(some_variable)[:4])

That will give you 0.94 on the brain screen. [:5] would give you 0.949, and so on.


#8

round()'s strange behavior here is a fun result of how that builtin function is implemented: it takes a float as an argument and it returns a float as its result. And, as you’ve guessed, 0.95 can’t be represented in floating point, since you can’t write it out as a binary fraction:

image

This oddity is noted in the official Python reference documentation:

The behavior of round() for floats can be surprising: for example, round(2.675, 2) gives 2.67 instead of the expected 2.68 . This is not a bug: it’s a result of the fact that most decimal fractions can’t be represented exactly as a float. See Floating Point Arithmetic: Issues and Limitations for more information.

Floating point precision display issues are in every language that uses them, including C and C++, but you can usually work around them with format strings. Unfortunately, those are not implemented in Pymite. @WillRobinson’s workaround is the best one I can think of.

We may port the Decimal library at some point in the future, since classroom robots do work with decimal values a lot.


#9

@WillRobinson, @RobotMesh_Support:

Thank you!