Как получить только первые 3 цифры номера? - PullRequest
0 голосов
/ 12 июля 2020

У меня есть вектор чисел (с плавающей запятой), представляющий все после секунды некоторой временной отметки. У них разная длина. Это выглядит примерно так:

4456

485926

346

...

Представляет 0,4456, 0,485926 и 0,346 секунды. соответственно. Мне нужно преобразовать каждый из них в миллисекунды, однако я не могу просто умножить каждое на некоторую константу, поскольку все они имеют разную длину. Я нормально теряю точность, мне просто нужны первые 3 цифры (бит миллисекунды). Как это сделать?

Ответы [ 4 ]

0 голосов
/ 12 июля 2020

Использование "(int) log10 + 1" - простой способ получить количество целых цифр

auto x = 485926;
auto len = (int)std::log10(x) + 1;

https://godbolt.org/z/v1jz7P

0 голосов
/ 12 июля 2020

Думаю, вам это не нужно для решения вашей проблемы. Попробуйте что-то вроде следующего

#include <vector>
#include <chrono>
#include <iostream>
#include <algorithm>

using namespace std::chrono;
int main(){
    std::vector decRep = {0.4456f, 0.485926f, 0.346f};
    std::vector<milliseconds> msRep(3);
    size_t i{};


    std::for_each(msRep.begin(), msRep.end(), [&](auto& el){
        el = milliseconds{static_cast<size_t>(decRep[i++]*1000)};
    });

    std::for_each(msRep.cbegin(), msRep.cend(), [](const auto& el){
        std::cout << el.count() << "ms  ";
    });
}

Live

Если ваши значения являются числами с плавающей запятой, имеющими форму 4456.0, 485926.0 и 346.0, вы можете использовать что-то вроде следующего

#include <vector>
#include <chrono>
#include <iostream>
#include <algorithm>
#include <string>

using namespace std::chrono;
int main(){
    std::vector decRep = {4456.f, 485926.f, 346.f};
    std::vector<milliseconds> msRep(3);
    size_t i{};


    std::for_each(msRep.begin(), msRep.end(), [&](auto& el){
        el = milliseconds{std::stoi(std::to_string(decRep[i++]).substr(0,3))};
    });

    std::for_each(msRep.cbegin(), msRep.cend(), [](const auto& el){
        std::cout << el.count() << "ms  ";
    });
}

Живое

0 голосов
/ 12 июля 2020

Попробуйте следующее:

#include <iostream>
#include <string>
using namespace std;

int getFirstThreeDigits(int number){
    return stoi(to_string(number).substr(0,3));
}

int main()
{
  float values[] = {4456, 485926, 346};
  int arrLength = (sizeof(values)/sizeof(*values));
  for( int i = 0 ; i < arrLength ; i++){
      cout << getFirstThreeDigits(values[i]) << endl;
  }
}
0 голосов
/ 12 июля 2020

Здесь я предполагаю, что часть интеграл числа с плавающей точкой представляет собой субсекундное значение, так что 1234f на самом деле составляет 0.1234 секунды. Кажется, именно об этом и говорится в вашем вопросе.

Если это так, мне кажется, вы можете просто непрерывно делить значение на десять, пока не получите что-то меньше единицы. Затем умножьте это на тысячу и округлите. Это будет go что-то вроде:

#include <iostream>

int millis(float value) {
    if (value < 0) return -millis(-value);
    //while (value >= 1000f) value /= 1000f;
    while (value >= 1.0f) value /= 10.f;
    return static_cast<int>(value * 1000 + .5f);
}

int main(int argc, char *argv[]) {
    for (int i = 1; i < argc; ++i) {
        float f= atof(argv[i]);
        std::cout << "   " << f << " -> " << millis(f) << "\n";
    }
}

Я также добавил специальный случай для обработки отрицательного числа и (закомментированный, необязательный) оптимизацию, чтобы быстрее перейти к под-единице для большие числа.

Далее следует стенограмма с вашими примерными значениями:

pax> ./testprog 4456 485926 346
   4456 -> 446
   485926 -> 486
   346 -> 346

Если вместо этого значения уже являются субсекундными числами с плавающей запятой, а вам просто нужно количество миллисекунд, вы делаете то же самое, но без начальных делений:

int millis(float value) {
    if (value < 0) return -millis(-value);
    return static_cast<int>(value * 1000 + .5f);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...