# Round to first significant digit

I want to round a decimal number (x), but I need to do it differently depending on how it is. If it has integer significant digits, we round to the nearest integer, and if not, we round to the first significant digit. So the following would happen with these example numbers: 11.871->12, 11.177->11, 37.233->37, 37.779->38, 0.578->0.6, 0.544->0.5, 0.0257->0.03, 0.0223->0.02... (The numbers could have more or less decimal places than in the examples).

To implement this, I have created a function (type) in which we check if the most significant digit is of type integer or decimal. This function returns this characteristic of the number in the form of a "string". So if the most significant digit is an integer we just use the "round()" function. However, I don't know how to round a number to the first significant digit (roundto_fsd() function). Does anyone know of any function capable of doing this or any method to do it?

``````float x;

char type(float number) {
char type[8];
if (int(number) != 0) {
type = "integer";
} else {
type = "decimal";
}
return type;
}

float roundto_fsd(float number) {}

void setup() {
Serial.begin(9600);
if (!type(x).compareTo("integer")) {
Serial.println(round(x));
} else if (!type(x).compareTo("decimal")) {
Serial.println(roundto_fsd(x));
}
}

void loop() {}
``````

First of all, let me clarify that there is nothing “decimal” in a `float`: a `float` is a binary (not decimal) floating point number. The `Serial.println()` function does a binary-to-decimal conversion for the purpose of representing the number as human-readable text. If you want a specific number of decimal digits after the radix point, you should ask `Serial.println()` to provide them. This is done by passing this number as a second parameter:

``````Serial.println(sqrt(2));    // prints "1.41" (2 decimals by default)
Serial.println(sqrt(2), 0); // prints "1"
Serial.println(sqrt(2), 5); // prints "1.41421"
``````

Now the question is: how to compute the number of required digits after the radix point? This depends on how big the `float` is. If it is smaller than 1 but larger or equal to 0.1, you want just one digit. If it is ten times smaller than that, you want to digits, and so on:

``````numbers      digits
───────────────────
[1, +∞)        0
[0.1, 1)       1
[0.01, 0.1)    2
[0.001, 0.01)  3
``````

I suggest repeatedly multiplying your `float` by 10 until it gets ≥ 1, and count the number of times you had to do so:

``````/* How many decimal places to print. */
int decimal_places(float x)
{
int i = 0;
while (x < 1) {
x *= 10;
i++;
}
return i;
}
``````

You would use this function like this:

``````Serial.println(x, decimal_places(x));
``````

Note that there is a small issue with this approach. If you try to print 0.97, `decimal_places()` will say you need one decimal, and `Serial.println()` will print “1.0”. If you would rather have it print “1”, then change the loop condition within `decimal_places()` to:

``````while (x < 0.95)
``````

Caveat: All this assumes that the numbers you want to print are all strictly larger than zero. Otherwise `decimal_places()` would have an infinite loop.

• Thank you! Is using the "while(x<0.95)" condition because Serial.print() rounds? May 21 at 21:24
• @Libegria: It's because `Serial.print()` rounds to nearest, meaning 0.97 would be rounded up to 1.0, but 0.93 would be rounded down to 0.9. May 21 at 21:47