Печать с округлением в сторону нуля вместо округления до ближайшего

При печати с одним знаком после запятой Serial.println() Arduino округляет числа вроде 123.89 до «123.9». Есть ли способ изменить режим округления? По некоторым причинам я хочу, чтобы значение округлялось в сторону нуля (т. е. усекалось) до одного знака после запятой, например 123.89 → «123.8».

вот код

void setup() {
Serial.begin(9600);

}

void loop() 
{
float A = analogRead(A0);
A = (A/1023)*5.0;
Serial.print("A = ");
Serial.println(A,3);
float B = A*10;
Serial.print("A * 10 = ");  
Serial.println(B,1);
delay(1000);
}

выход

A = 2.473
A * 10 = 24.7
A = 2.488
A * 10 = 24.9
A = 2.517
A * 10 = 25.2
A = 2.527
A * 10 = 25.3
A = 2.507
A * 10 = 25.1

вместо этого я хочу, чтобы вывод был таким

A = 2.473
A * 10 = 24.7
A = 2.488
A * 10 = 24.8
A = 2.517
A * 10 = 25.1
A = 2.527
A * 10 = 25.2
A = 2.507
A * 10 = 25.0

это возможно?

, 👍2


2 ответа


Лучший ответ:

8

Простой трюк для округления числа до одного десятичного знака (в «режиме обрезания») — умножить его на 10, преобразовать в целое число и снова разделить на 10.0f:

float myVal = 123.89f;
myVal = (long)(myVal * 10) / 10.0f;
// = ((long)1238.9) / 10.0f
// = 1238 / 10.0f
// = 123.8

Затем вы можете распечатать этот измененный номер на последовательном мониторе.

Этот метод можно также обобщить для других значений точности. Для 2 знаков после запятой нам просто нужно умножить на 10^2 (100) и разделить на 10^2. Макрос будет таким:

#define TRUNCATE(val, numDecimalPlaces) \
    (float)(((long)((double)(val) * pow(10, (numDecimalPlaces) * 1.0f))) / (pow(10, (numDecimalPlaces)* 1.0f)))

Примечание: вам не нужно фактически динамически вычислять pow(10, numDecimalPlaces), вы также можете создать макросы для каждой десятичной точности от 1 до x и просто предварительно вычислить это значение (100, 1000, 10000, ..).

Того же самого можно добиться, используя стандартную библиотечную функцию trunc из math.h:

#define TRUNCATE_TO_ONE(val) \
    (trunc((val) * 10.0f) / 10.0f)

См. http://www.cplusplus.com/reference/cmath/trunc/.

Вот небольшая зарисовка, в которой это продемонстрировано:

#include <Arduino.h>

#define TRUNCATE(val, numDecimalPlaces) \
    (float)(((long)((double)(val) * pow(10, (numDecimalPlaces) * 1.0f))) / (pow(10, (numDecimalPlaces)* 1.0f)))

#define TRUNCATE_TO_ONE(val) \
    (trunc((val) * 10.0f) / 10.0f)


void printValueFormatted(float value, int numDecimalPlaces) {
    //format correctly
    char buf[20];
    char* res = dtostrf(value, sizeof(buf)-1, numDecimalPlaces, buf);

    //skip over empty chars
    while(*res == ' ')
        res++;

    //print buffer
    Serial.println(res);
}


void setup(void)
{
    Serial.begin(115200);
}

void loop(void)
{
    float myVal = 123.8978f;
    printValueFormatted(myVal, 4);
    printValueFormatted(TRUNCATE(myVal, 1), 1);
    printValueFormatted(TRUNCATE(myVal, 2), 2);
    printValueFormatted(TRUNCATE(myVal, 3), 3);
    printValueFormatted(TRUNCATE(myVal, 1), 4);
    printValueFormatted(TRUNCATE(myVal, 2), 4);
    printValueFormatted(TRUNCATE(myVal, 3), 4);
    delay(1000);
}

Печатные издания

123.8978
123.8
123.89
123.897
123.8000
123.8900
123.8970
,

0

Используйте данную [функцию] для вашей проблемы. Эта функция работает по предопределенному [алгоритму].

int roundTowardZero(float number, int decimal_place) {
    float round_number = round(number);
    if(round_number > number) round_number = round_number - 1;
    float deci = (number - round_number) * pow(10, decimal_place);
    float round_decimal = round(deci);
    if(round_decimal > deci) round_decimal = round_decimal - 1;
    round_decimal = round_decimal / pow(10, decimal_place);
    total_number = round_number + round_decimal;
    return total_number;
}

Поместите эту функцию выше int setup()

нравится:

int roundTowardZero( ... ) {
    ...
}
void setup() {
    ...
}
void loop() {
    ...
}

Синтаксис функции выглядит следующим образом: roundTowardZero([Введите десятичное значение], [Введите значение разряда округления]) Пример:roundTowardZero(123.89, 1) //Выход: 123.8

Пожалуйста, оставьте комментарий ниже, если вы обнаружили какую-либо проблему или столкнулись с какой-либо ошибкой.

,