Zaokrąglenie liczby double

Zaokrąglenie liczby double
mati123kowal
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1
1

Witam,
Mam mały problem z zaokrągleniem zmiennej double do dwóch miejsc po przecinku. Mianowicie korzystając z std::round i std::floor efekt funkcji getTemp() jest taki jak na screenie:
screenshot-20241014123319.png
Wykorzystuję funkcję roundDouble(widać ją na dole screena) w takim przypadku:

Kopiuj
double BME280::getTemp(){
	uint8_t buffer[3];
    int32_t adc_T;
    int32_t var1, var2;
    int32_t temp;
    int32_t t_fine;

    HAL_I2C_Mem_Read(i2c, 0x76 << 1, 0xFA, 1, static_cast<uint8_t*>(buffer), 3, timeout);

    // Change result to 12-bit value:
    adc_T = static_cast<int32_t>(
    		(static_cast<uint32_t>(buffer[0]) << 12) |
			(static_cast<uint32_t>(buffer[1]) << 4) |
			(static_cast<uint32_t>(buffer[2]) >> 4));

    // Calculating temperature:
    var1 = static_cast<int32_t>((adc_T >> 3) - (static_cast<int32_t>(dig_T1) << 1));
    var1 = (var1 * static_cast<int32_t>(dig_T2)) >> 11;

    var2 = static_cast<int32_t>(((adc_T >> 4) - static_cast<int32_t>(dig_T1)) *
            ((adc_T >> 4) - static_cast<int32_t>(dig_T1)) >> 12);
    var2 = (var2 * static_cast<int32_t>(dig_T3)) >> 14;

    // Converting into celsius degrees:
    t_fine = var1 + var2;
    temp = (t_fine * 5 + 128) >> 8;
    double temperature = temp / 100.0;

    return roundDouble(temperature);
}

double BME280::roundDouble(double number){
	return std::round(number * 100.0) / 100.0;
}

Czy jest ktoś w stanie mi pomóc bo chat już nie ma pomysłów hah ?
PS: Z góry sorry za błędy w kodzie programuje w c++ obiektowo od 3 miesięcy...

MarekR22
  • Rejestracja: dni
  • Ostatnio: dni
4
  1. Takie rzeczy zaokrągla się na etapie konwersji do napisu, a nie numerycznie.
  2. co włąsciwie widać na pierwszym obrazku
  3. Ułamki dziesiętne nie mają dokładnej reprezentacji w wbudowanych typach zmiennoprzecinkowych (tam samo jak 1/3 w w ułamkach dziesiętnych), więc zakładając, że pokazujesz zawartość debuggera na pierwszym obrazku, to to jest "normalne".
Riddle
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 10227
0
mati123kowal napisał(a):

Witam,

Cześć @mati123kowal! 👋 Fajnie że jesteś na forum!

mati123kowal napisał(a):

Wykorzystuję funkcję roundDouble (widać ją na dole screena) w takim przypadku:

Mała prośba, czy mógłbyś umieścić kod na stronie jako jako tekst, najlepiej w znacznikach ```? 🙏

99xmarcin
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 2420
0

Nie trzeba było spać na studiach: screenshot-20241014191122.png

0.1 ma nieskończone rozwinięcie binarne, taka liczba gdy się ją wciśnie w double zawsze jest obarczona błędem.

Jak chcesz tego uniknąć to trzymaj swój wynik w longu lub własnej klasie na liczbę z 2 miejscami po przecinku.

Manna5
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Kraków
  • Postów: 667
0

Możesz spróbować jeszcze takiego sposobu, ale pamiętaj, że obliczenia zmiennoprzecinkowe nigdy nie będą całkowicie dokładne.

Kopiuj
#include <math.h>
double zaokr (double x)
{
        if (x >= 0.0)
                x += 0.005;
        else
                x -= 0.005;
        return x - fmod (x, 0.01);
}

Zaokrąglenie na etapie konwersji do napisu, jak napisał @MarekR22, można wykonać następująco:

Kopiuj
#include <stdio.h>

/* ... */

double liczba;
char napis[20]; /* Temperatura powinna się zmieścić na 19 znakach */
/* ... */

sprintf (napis, "%.2f", liczba); /* Zamień na tekst z 2 miejscami dziesiętnymi. */
/* Teraz napis to łańcuch znaków, który możesz wyświetlić np. na wyświetlaczu LCD jeśli to embedded.
Na dobrą sprawę to jest zwykłe obcięcie dalszych miejsc a nie zaokrąglenie, ale może wystarczy. */

/* ... */

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.