Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.73/37: Рейтинг темы: голосов - 37, средняя оценка - 4.73
Эксперт JavaЭксперт по электроникеЭксперт .NET
 Аватар для wizard41
3463 / 2784 / 575
Регистрация: 04.09.2018
Сообщений: 8,757
Записей в блоге: 3
.NET 4.x

Быстрейший способ отделить число от букв

13.09.2024, 13:11. Показов 9730. Ответов 117
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем привет.
Есть строки такого вида:
Code
1
2
3
4
1.5224V
1.5225mV
1.526 mV
1.527 V
Соответственно, число - это значение (всегда double!), а буквы - ед. измерения.
Необходимо наиболее быстро распарсить их.

Из строк видно, что они могут быть с четырьмя знаками после запятой, и в этом случае не содержат пробела между числом и строкой, и с тремя знаками, но уже с пробелом между ними.

Сначала первый вариант (без пробела) я парсил так:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
if (RegexPattern.IsFiltered(message))
{
    const string numbers = "0123456789.";
    var numberBuilder = new StringBuilder();
    var unitBuilder = new StringBuilder();
 
    foreach (char c in message)
    {
        if (numbers.IndexOf(c) > -1)
            numberBuilder.Append(c);
        else
            unitBuilder.Append(c);
    }
 
    double.TryParse(numberBuilder.ToString(), out double value);
    rawVoltage = value;
    Mv = unitBuilder.ToString() == "mV";
}
а второй просто Regex'ом: @"^\d+\.\d+\s{1}m?V$"

Затем сделал "общий" Regex для обоих этих случаев: @"^\d+\.\d+\s?m?V$"
и теперь их значения достаю вот так:
C#
1
2
3
4
5
6
if (IsVoltage(s))
{
    Console.Write($"Voltage: {RegexVoltageValue().Match(s).Value}\t");
    Console.Write($"Unit: {RegexUnitValue().Match(s).Value}");
    Console.WriteLine();
}
где сами регулярки такие:
C#
1
2
3
4
5
[GeneratedRegex(@"\d+\.\d+")]
private static partial Regex RegexVoltageValue();
 
[GeneratedRegex(@"(m?V)$")]
private static partial Regex RegexUnitValue();
По скорости работы StringBuilder VS Regex, вроде бы, немного выигрывает Regex, однако где-то я читал, что они медленнее, чем выборка нужного из цикла..
На простом коде сложно определить, т.к. разница незначительна, но вдруг случится "что-то", что намного затормозит этот процесс с Regex'ом?
Т.е. не поменял ли я шило на мыло?
1
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
13.09.2024, 13:11
Ответы с готовыми решениями:

Отделить цифры от букв и найти сумму цифр
Есть массив,N размера.В массиве присутствуют буквы и цифры.Нужно отделить цифры от букв и найти сумму цифр: отделяем буквы от цифр: ...

Автомобильные номера состоят из 1,2, или 3 букв и 4 цифр. используется 30 букв, найти число таких букв
Автомобильные номера состоят из 1,2, или 3 букв и 4 цифр. используется 30 букв, найти число таких букв. помогите решить, или объясните...

отделить крупное число от мелкого
например ввожу 4530 результат 4500 и 30 3456 3400 и 56 и т. д.

117
Эксперт JavaЭксперт по электроникеЭксперт .NET
 Аватар для wizard41
3463 / 2784 / 575
Регистрация: 04.09.2018
Сообщений: 8,757
Записей в блоге: 3
21.09.2024, 18:59  [ТС]
Студворк — интернет-сервис помощи студентам
VBDUnit, благодарю за участие, в качестве разминки предложенный вариант сгодится.
Но за unsafe будут бить по рукам дубиной. Долго.
1
178 / 33 / 17
Регистрация: 02.02.2014
Сообщений: 373
21.09.2024, 19:05
Цитата Сообщение от wizard41 Посмотреть сообщение
Но за unsafe будут бить по рукам дубиной. Долго.
Привычка Я в своих проектах активно юзаю и unsafe, и C++, и симды - без этого никак (всё предварительно обмазывается проверками/блокировками, защищающими от выстрелов в ногу).

А так - эти оптимизации можно и без unsafe сделать, если местные правила не позволяют. Будет лишь немного медленнее.
0
22.09.2024, 00:09

Не по теме:

Цитата Сообщение от VBDUnit Посмотреть сообщение
decimal nanoseconds = stopw.ElapsedMilliseconds * 1m * 1000 * 1000;
Ужс. Там же есть TimeSpan....

0
 Аватар для belalugoci
475 / 294 / 29
Регистрация: 01.06.2018
Сообщений: 3,676
22.09.2024, 04:23
VBDUnit, про enum подумал вчера, но до понедельника попробовать всё равно не смогу, как раз интересно проверить что это изменит в моем варианте.
Про таблицы значений я думал когда делал свой парсер double, так как такое постоянно применяю на ретро-системах, но если честно создание таблиц оправдано только при их постоянном использовании для большого числа значений, для 4 строк генерация 10000 элементов массива имхо будет накладной, поэтому даже не стал проверять такой вариант, хотя он вроде бы должен удовлетворять тому как используется приложение самим автором.
0
 Аватар для belalugoci
475 / 294 / 29
Регистрация: 01.06.2018
Сообщений: 3,676
23.09.2024, 09:41
VBDUnit, wizard41,
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
| Method           | source   | Mean          | Error         | StdDev        | Gen0     | Gen1     | Gen2     | Allocated |
|----------------- |--------- |--------------:|--------------:|--------------:|---------:|---------:|---------:|----------:|
| ParseNew2        | 1,5224V  |      96.13 ns |      0.476 ns |      0.422 ns |        - |        - |        - |         - |
| ParseFastParser3 | 1,5224V  | 602,952.90 ns | 11,531.706 ns | 12,338.796 ns | 488.2813 | 480.4688 | 479.4922 | 2176568 B |
 
| ParseNew2        | 1,5225mV |      94.11 ns |      0.511 ns |      0.478 ns |        - |        - |        - |         - |
| ParseFastParser3 | 1,5225mV | 614,337.61 ns | 12,254.469 ns | 22,714.445 ns | 486.3281 | 476.5625 | 475.5859 | 2176567 B 
 
| ParseNew2        | 1,526 mV |      92.32 ns |      0.182 ns |      0.161 ns |        - |        - |        - |         - |
| ParseFastParser3 | 1,526 mV | 611,784.66 ns | 11,903.226 ns | 18,531.890 ns | 485.3516 | 479.4922 | 478.5156 | 2176567 B |
 
| ParseNew2        | 1,527 V  |      90.26 ns |      0.168 ns |      0.149 ns |        - |        - |        - |         - |
| ParseFastParser3 | 1,527 V  | 597,903.19 ns | 11,831.719 ns | 15,795.006 ns | 486.3281 | 474.6094 | 474.6094 | 2176565 B |
1. Enum имеет смысл вводить только если на стороне клиента возврат значения в таком формате актуален, иначе конвертация в string на этапе возврата убивает возможные плюсы.
2. Как я и предполагал - слишком большие накладные расходы на создание таблиц.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,175
Записей в блоге: 2
29.09.2024, 19:43
Цитата Сообщение от wizard41 Посмотреть сообщение
Есть строки такого вида:
Случайно наткнулся на тему - не читал всю.
Может уже кто-то и предложил. Без учёта культуры (всегда точка) и строго по формату. То есть: число, точка, число, если число меньше 4 разрядов, то обязательно пробел после него.


C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
    public static partial class Helper
    {
        public static double DoubleParse(this ReadOnlySpan<char> line)
        {
            double result = 0;
            int i = 0;
            for (;line[i] != '.'; i++)
            {
                result *= 10;
                result += line[i] - '0';
            }
            double place = 0.1;
            i++;
            int j = i + 4;
            for (; i < j && line[i] != ' '; i++)
            {
                result += (line[i] - '0') * place;
                place *= 0.1;
            }
            return result;
        }
        public static double DoubleParse(this string line)
        {
            double result = 0;
            int i = 0;
            for (;line[i] != '.'; i++)
            {
                result *= 10;
                result += line[i] - '0';
            }
            double place = 0.1;
            i++;
            int j = i + 4;
            for (; i < j && line[i] != ' '; i++)
            {
                result += (line[i] - '0') * place;
                place *= 0.1;
            }
            return result;
        }
        public static double DoubleParse(this IEnumerable<char> line)
        {
            var numerator = line.GetEnumerator();
            double result = 0;
            while(numerator.MoveNext())
            {
                if (numerator.Current == '.')
                    break;
                result *= 10;
                result += numerator.Current - '0';
            }
 
            int i = 0;
            double place = 0.1;
            while (numerator.MoveNext())
            {
                if (numerator.Current == ' ' || i >= 4)
                    break;
                result += (numerator.Current - '0') * place;
                place *= 0.1;
                i++;
            }
            return result;
        }
    }
1
 Аватар для belalugoci
475 / 294 / 29
Регистрация: 01.06.2018
Сообщений: 3,676
30.09.2024, 09:08
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Может уже кто-то и предложил
Подумал что у нас несколько плоский тест, так как тестовые значения практически все одинаковые, хотя диапазон чисел может быть сильно шире, что повлияет на скорость работы. Так что я сделал новый набор
C#
1
[Params("1,5224V", "291,5225mV", "0,5   mV", "201,527 V")]
и вот результат теста
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
| Method          | source     | Mean      | Error    | StdDev   | Allocated |
|---------------- |----------- |----------:|---------:|---------:|----------:|
| ParseNew2       | 0,5   mV   |  85.59 ns | 0.390 ns | 0.326 ns |         - |
| ParseEldHasp    | 0,5   mV   |  10.92 ns | 0.068 ns | 0.064 ns |         - |
 
| ParseNew2       | 1,5224V    |  93.85 ns | 0.357 ns | 0.316 ns |         - |
| ParseEldHasp    | 1,5224V    |  14.82 ns | 0.018 ns | 0.015 ns |         - |
 
| ParseNew2       | 201,527 V  | 103.35 ns | 0.285 ns | 0.267 ns |         - |
| ParseEldHasp    | 201,527 V  |  17.50 ns | 0.028 ns | 0.023 ns |         - |
 
| ParseNew2       | 291,5225mV | 108.20 ns | 0.294 ns | 0.230 ns |         - |
| ParseEldHasp    | 291,5225mV |  18.72 ns | 0.035 ns | 0.033 ns |         - |
Весьма отличный результат!

Посмотрите, я правильно тест сделал?
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
    [Benchmark]
    public (double, string) ParseEldHasp() => ParceEldHaspMathod(source);
 
    static (double, string) ParceEldHaspMathod(ReadOnlySpan<char> s)
    {
        int ss = (int)s[^2] == 109 ? 1 : 0;
        return (DoubleParse(s.Slice(0, s.Length - 1 - ss)), ss == 0 ? "V" : "mV");
    }
    static double DoubleParse(ReadOnlySpan<char> line)
    {
        double result = 0;
        int i = 0;
        for (; line[i] != ','; i++)
        {
            result *= 10;
            result += line[i] - '0';
        }
        double place = 0.1;
        i++;
        int j = i + 4;
        for (; i < j && line[i] != ' '; i++)
        {
            result += (line[i] - '0') * place;
            place *= 0.1;
        }
        return result;
    }
а то я тот еще кадр и мог накосячить.
2
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,175
Записей в блоге: 2
30.09.2024, 13:35
Цитата Сообщение от belalugoci Посмотреть сообщение
Посмотрите, я правильно тест сделал?
Я не дока по тестам.
Но что вижу "невооружённым глазом":
- Во время выполнение входит и подготовка источника - тело метода ParceEldHaspMathod;
- Я сделал три перегрузки метода. И в зависимости от типа исходных данных надо применять наиболее подходящую. Изначально прочитал, что входные данные поступают в string[]. Соответственно, лучшая перегрузка это будет DoubleParse(this string line);
- Если говорить о задаче в целом, то здесь нужно ещё и решение от wizard41. Массив строк тоже берётся не сам по себе из вакуума. Есть какой-то поток данных. Так как парсинг в строки это всегда медленно, то имеет смысл подумать как парсить числа сразу из входного потока.

Добавлено через 4 минуты
В самом методе есть тяжёлое место - приведение каждого символа из int в double.
На ассемблере это можно сильно ускорить. Как сделать на Шарпе... нужно хорошенько подумать.
0
 Аватар для belalugoci
475 / 294 / 29
Регистрация: 01.06.2018
Сообщений: 3,676
30.09.2024, 13:42
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Я не дока по тестам.
я писал всем.

Цитата Сообщение от Элд Хасп Посмотреть сообщение
В самом методе есть тяжёлое место - приведение каждого символа из int в double.
На ассемблере это можно сильно ускорить. Как сделать на Шарпе... нужно хорошенько подумать.
если честно я надеялся что стандартный double.Parse() сделан весьма хитро и с учетом всякого, как оказывается - нет.
0
Эксперт JavaЭксперт по электроникеЭксперт .NET
 Аватар для wizard41
3463 / 2784 / 575
Регистрация: 04.09.2018
Сообщений: 8,757
Записей в блоге: 3
30.09.2024, 13:47  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
здесь нужно ещё и решение от wizard41
пока остановился на варианте от kolorotur.
Задача, в общем то, не про то как "изобрести" новый быстрый метод парсинга, а в том, чтобы выбрать быстрейший из имеющихся 'стандартных' подходов.
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Массив строк тоже берётся не сам по себе из вакуума. Есть какой-то поток данных.
Да, этот поток берется из COM-порта каждые 100 мс.
Цитата Сообщение от Элд Хасп Посмотреть сообщение
как парсить числа сразу из входного потока
Как раз это и обсуждается здесь, т.к. парсинг и чисел и символов происходит тут же, при получении очередного пакета.

Изначально, мне казалось, что используемый мной подход с циклом - через чур "напряжный". Ну а дальше исходя из тестов выяснилось, что он довольно медленный, по сравнению с предложенными.

Добавлено через 2 минуты
Цитата Сообщение от belalugoci Посмотреть сообщение
Посмотрите, я правильно тест сделал?
Сойдет.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,175
Записей в блоге: 2
30.09.2024, 14:03
Вот улучшенный метод - в нём только одно приведение к double:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
        public static double DoubleParseBettered(this string line)
        {
            int intresult = 0;
            int i = 0;
            int indpoint = 0;
            for (; line[i] != ' ' && i < indpoint + 5; i++)
            {
                if(line[i] == '.')
                {
                    indpoint = i;
                    continue;
                }
                intresult *= 10;
                intresult += line[i] - '0';
            }
            double result = (i - indpoint) switch
            {
                1 => intresult,
                2 => intresult * div1,
                3 => intresult * div2,
                4 => intresult * div3,
                5 => intresult * div4,
                _ => throw new NotImplementedException()
            };
            return result;
        }
Добавлено через 3 минуты
Цитата Сообщение от wizard41 Посмотреть сообщение
Да, этот поток берется из COM-порта каждые 100 мс.
То есть байтовый поток.
Это точно не юникод. Или ASCII или, вообще, цифровой целочисленный формат.
Надо из байтов сразу парсить.

Добавлено через 2 минуты
Цитата Сообщение от belalugoci Посмотреть сообщение
если честно я надеялся что стандартный double.Parse() сделан весьма хитро и с учетом всякого, как оказывается - нет.
Он очень тяжёлый, так как должен учитывать все возможные форматы (научный, например), все культуры (в том числе кастомные) и пользовательские строки формата.
0
 Аватар для belalugoci
475 / 294 / 29
Регистрация: 01.06.2018
Сообщений: 3,676
30.09.2024, 14:49
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Вот улучшенный метод
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| Method          | source     | Mean      | Error    | StdDev   | Allocated |
|---------------- |----------- |----------:|---------:|---------:|----------:|
| ParseNew2       | 0,5   mV   |  82.09 ns | 0.157 ns | 0.139 ns |         - |
| ParseEldHasp    | 0,5   mV   |  10.91 ns | 0.027 ns | 0.024 ns |         - |
| ParseEldHaspMod | 0,5   mV   |  13.35 ns | 0.039 ns | 0.036 ns |         - |
 
| ParseNew2       | 1,5224V    |  94.84 ns | 0.179 ns | 0.139 ns |         - |
| ParseEldHasp    | 1,5224V    |  15.05 ns | 0.075 ns | 0.067 ns |         - |
| ParseEldHaspMod | 1,5224V    |  15.90 ns | 0.031 ns | 0.026 ns |         - |
 
| ParseNew2       | 201,527 V  | 107.26 ns | 0.053 ns | 0.044 ns |         - |
| ParseEldHasp    | 201,527 V  |  17.55 ns | 0.068 ns | 0.064 ns |         - |
| ParseEldHaspMod | 201,527 V  |  15.80 ns | 0.024 ns | 0.021 ns |         - |
 
| ParseNew2       | 291,5225mV | 108.78 ns | 0.382 ns | 0.357 ns |         - |
| ParseEldHasp    | 291,5225mV |  18.70 ns | 0.023 ns | 0.020 ns |         - |
| ParseEldHaspMod | 291,5225mV |  15.82 ns | 0.079 ns | 0.070 ns |         - |
эффект наблюдается для длинных чисел.
кстати я правильно понял ваш код?
C#
1
2
3
4
5
                1 => intresult,
                2 => intresult * div1,
                3 => intresult * div2,
                4 => intresult * div3,
                5 => intresult * div4,
заменил на
C#
1
2
3
4
5
            1 => intresult,
            2 => intresult * 0.1,
            3 => intresult * 0.01,
            4 => intresult * 0.001,
            5 => intresult * 0.0001,
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,175
Записей в блоге: 2
30.09.2024, 15:28
Цитата Сообщение от belalugoci Посмотреть сообщение
заменил на
Да.
Разницы нет.
Компилятор на оба варианта выдаст одинаковый код.

Добавлено через 2 минуты
Цитата Сообщение от belalugoci Посмотреть сообщение
эффект наблюдается для длинных чисел.
Больше пока у меня нет идей.
Только прямая обработка байтового потока без его преобразования в стринги.
0
 Аватар для belalugoci
475 / 294 / 29
Регистрация: 01.06.2018
Сообщений: 3,676
30.09.2024, 16:04
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Да.
Разницы нет.
Компилятор на оба варианта выдаст одинаковый код.
) нет, ваш вариант не скомпилируется там как нет определения того что такое div1-4.

Цитата Сообщение от Элд Хасп Посмотреть сообщение
Только прямая обработка байтового потока без его преобразования в стринги.
я так всегда работаю с текстом, я не использую unicode для данных, мне достаточно ascii.
1
 Аватар для Andrey-MSK
3397 / 2283 / 388
Регистрация: 14.08.2018
Сообщений: 7,749
Записей в блоге: 4
30.09.2024, 16:04
Цитата Сообщение от Элд Хасп Посмотреть сообщение
в стринги

Не по теме:

В семейники продуктивнее будет


1
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,175
Записей в блоге: 2
30.09.2024, 18:55
Цитата Сообщение от belalugoci Посмотреть сообщение
нет, ваш вариант не скомпилируется там как нет определения того что такое div1-4.
Ох...
Ёлки-палки!
Пропустил при копировании.
Это у меня константы с такими именами были объявлены.

Добавлено через 2 минуты
Цитата Сообщение от belalugoci Посмотреть сообщение
я так всегда работаю с текстом, я не использую unicode для данных, мне достаточно ascii.
Зависит от исходных данных.
Мелкие простые устройства практически никогда не используют юникод.
0
Эксперт JavaЭксперт по электроникеЭксперт .NET
 Аватар для wizard41
3463 / 2784 / 575
Регистрация: 04.09.2018
Сообщений: 8,757
Записей в блоге: 3
30.09.2024, 19:32  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Надо из байтов сразу парсить.
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Только прямая обработка байтового потока без его преобразования в стринги.
В данном случае не подходит.
Во первых: сервис, отправляющий и получающий данные с порта - отдает внешнему коду результат полученных данных в виде string.
Во вторых: входящие данные - не всегда имеют формат <число><размерность>; это могут быть и информационные (текстовые) сообщения или результаты выполнения каких-либо команд.
Нет смысла в приемнике парсить строки вида:
+3.300000E-03
V1.1.1
1.
-F 1
9.0000009

... и т.п.
Более того, этот же сервис используется для приема конкретно текстовой информации, которую парсить точно не нужно.
Поэтому, в теле Event'а от приемника определены правила (Regex), которые сначала определяют что именно получено, а затем уже выполняются определенные операции..
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,175
Записей в блоге: 2
30.09.2024, 23:16
Цитата Сообщение от wizard41 Посмотреть сообщение
В данном случае не подходит.
Ну, судя по вашему описанию, там нет никакого смыла экономить доли миллисекунд, не говоря уже о наносекундах.
Оптимальность в данном случае - это понятность и простота кода.
1
Эксперт JavaЭксперт по электроникеЭксперт .NET
 Аватар для wizard41
3463 / 2784 / 575
Регистрация: 04.09.2018
Сообщений: 8,757
Записей в блоге: 3
01.10.2024, 23:27  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
нет никакого смыла экономить доли миллисекунд, не говоря уже о наносекундах
Конечно же.
Элд Хасп, эмм... в свете названия темы, (может я не очень удачно ее назвал) ваше и другие решения имеют право на существование. А возможно покажутся полезными кому-то еще.
Понятно дело, что я преследовал свою конкретную цель, задавая такой вопрос. Тем не менее, мои сомнения развеялись и, более того, нашлись варианты получше моих.
Казалось бы, банальная вещь: распарсить строку, но, оказывается есть приложения, где время выполнения этого весьма критично.
Элд Хасп, спасибо вам за участие, но проверять (тестировать) методики уже нет времени - у меня жесткий дедлайн... Занимаюсь другими вопросами.
0
 Аватар для belalugoci
475 / 294 / 29
Регистрация: 01.06.2018
Сообщений: 3,676
02.10.2024, 13:44
Цитата Сообщение от wizard41 Посмотреть сообщение
может я не очень удачно ее назвал
норм, было прикольно поковыряться в вопросе на скорость, Элд Хасп лишний раз мне показал, что нужно пробовать простые варианты реализации, а не уповать на то, что MS всё сделали оптимально.

Добавлено через 5 часов 39 минут
Элд Хасп, я тут всё еще ковыряюсь в теме, делал тест и у меня получилось для ваших двух вариантов такое непотребство:
в таблице ниже:
слева ваш результат после преобразования в строку
C#
1
var result = string.Concat(values.Item1.ToString(), values.Item2);
справа оригинальные данные с вырезанными пробелами кодом
C#
1
2
3
4
5
6
    StringBuilder sb = new StringBuilder();
    foreach ( var sbs in orig_str )
    {
        if (sbs != ' ')
            sb.Append(sbs);
    }
использовал два метода:
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
static (double, string) Method4(ReadOnlySpan<char> s)
{
    int ss = (int)s[^2] == 109 ? 1 : 0;
    return (DoubleParse(s.Slice(0, s.Length - 1 - ss)), ss == 0 ? "V" : "mV");
}
static double DoubleParse(ReadOnlySpan<char> line)
{
    double result = 0;
    int i = 0;
    for (; line[i] != ','; i++)
    {
        result *= 10;
        result += line[i] - '0';
    }
    double place = 0.1;
    i++;
    int j = i + 4;
    for (; i < j && line[i] != ' '; i++)
    {
        result += (line[i] - '0') * place;
        place *= 0.1;
    }
    return result;
}
static (double, string) Method5(ReadOnlySpan<char> s)
{
    int ss = (int)s[^2] == 109 ? 1 : 0;
    return (DoubleParseBettered(s.Slice(0, s.Length - 1 - ss)), ss == 0 ? "V" : "mV");
}
static double DoubleParseBettered(ReadOnlySpan<char> line)
{
    int intresult = 0;
    int i = 0;
    int indpoint = 0;
    for (; line[i] != ' ' && i < indpoint + 5; i++)
    {
        if (line[i] == '.')
        {
            indpoint = i;
            continue;
        }
        intresult *= 10;
        intresult += line[i] - '0';
    }
    double result = (i - indpoint) switch
    {
        1 => intresult,
        2 => intresult * 0.1,
        3 => intresult * 0.01,
        4 => intresult * 0.001,
        5 => intresult * 0.0001,
        _ => throw new NotImplementedException()
    };
    return result;
}

Code
1
2
3
4
5
6
7
8
9
10
11
Method4 (DoubleParse):
|1,5224V|, |1,5224V|
|291,5225mV|, |291,5225mV|
|0,5mV|, |0,5mV|
|201,52700000000002V|, |201,527V|
 
Method5 (DoubleParseBettered):
|0,6522V|, |1,5224V|
|2,9065000000000003mV|, |291,5225mV|
|-0,35000000000000003mV|, |0,5mV|
|2,0065V|, |201,527V|
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
02.10.2024, 13:44

Строка: Есть ли способ одной строкой менять несколько букв?
var a, b : string; begin a := 'ПРИВЕТ'; b := StringReplace(a, 'П', 'В', ); b := StringReplace(a, 'Р', 'О', ); b :=...

Как преобразовать строку, удалив в ней группы цифр, а группы букв отделить пробелами. Упорядочить полученную последовательность слов
Дана текстовая строка, состоящая из букв и цифр. Преобразовать строку, удалив в ней группы цифр, а группы букв отделить пробелами....

Сумма кодов первой и последней букв: способ разрешения коллизий Бинарное дерево
Привет. Помогите, пожалуйста, с написанием программы: Тип хеш-функции (таблицы)-Сумма кодов первой и последней букв Способ разрешения...

Подсчитать число гласных и согласных букв в множестве и определить, каких букв больше
Подсчитать число гласных и согласных букв в множестве и определить, каких букв больше. Учесть, что в строке могут быть другие символы,...

Перед каждой группой одинаковых букв, вставить число, соответствующее количеству букв
Помогите пожалуйста, очень прощу! В слове, состоящим из цифр и букв и заканчивающимся точкой, перед каждой группой одинаковых букв,...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
100
Ответ Создать тему
Новые блоги и статьи
Запрет дублирования строк в табличной части
Maks 13.09.2026
Реализация из решения ниже выполнена на нетиповом справочнике "Нормы ТО" с табличной часть "Виды ТО", разработанного в КА2, со следующими реквизитами: - ВидТО (СправочникСсылка. ВидыТО); - ВидГСМ. . .
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
Программа опроса у.з. расходомера SLS-720F
Argus19 02.09.2026
Программа опроса у. з. расходомера SLS-720F Программа опрашивает один раз в минуту три ультразвуковых расходомера SLS-720F через интерфейс RS-485 по протоколу Modbus RTU. Опрашиваются регистры. . .
Hyper-V: Компьютер должен поддерживать доверенный платформенный модуль 2.0.
Maks 31.08.2026
При установке Windows 11 на виртуальную машину Hyper-V 2-го поколения вылезла такая ошибка: Решение: в параметрах виртуальной машины, в разделе "Безопасность" (Security) активировать флаг. . .
Архитектура биовида Стива в Майнкрафте: Зачем бонобо кубический каннибализм
anaschu 30.08.2026
Кубический Вагинокапитализм в Minecraft: Математический инвариант ОДУ и рок Стивов-бонобо Главная задача разработанной «Модели Всего» — наглядно продемонстрировать наличие системной «судьбы». . .
Оттачиваю умение писать js программы.
russiannick 30.08.2026
Проектом выходного дня стало написание Книги шифров Виженера. Итогом стала версия 200, синий туман. Синий туман назван так, потому что замораживает текст под собой. Нажатие синих кнопок управляют. . .
мат медиц модель 30. презентация проекта
anaschu 27.08.2026
хоп хоп хоп хидахоп, а я кладую))
Как у меня протекала болезнь
zorxor 27.08.2026
Здравствуйте, друзья! Эта запись блога предназначена именно для вас - для моих дорогих друзей, которые знали меня лично. Чтобы ответить на вопрос - а что же со мной произошло на самом деле? Я учился. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru