Linqpad обрезает все числовые поля до 4 знаков после запятой в выводе дампа

Поддерживает ли Linqpad усечение числовых полей до максимального количества знаков после запятой, аналогично параметрам конфигурации «Результаты», которые применяются к выходу DateTime:

Предполагая, что Linqpad не имеет встроенной поддержки (нет опции на вкладке настроек «Результаты»), есть ли другие варианты? У меня есть объект on с более чем сотнями double свойств, и я стараюсь не писать Math.Round(obj.Property, 4, MidpointRound.ToZero) 200 раз.

Нет. Числа хранятся в двоичном формате и не преобразуются в десятичные разряды. Таким образом, единственный способ усечения до десятичных разрядов - сначала преобразовать число в строку, а затем обрезать строку.

jdweng 07.10.2022 08:14
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
1
70
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

С Linqpad 7 вы можете настроить команду дампа, добавив ее в свой запрос.

static object ToDump(object o)
{
    if (o is double d) return Math.Round(d, 4, MidpointRounding.ToZero);
    return o;
}

Пример

void Main()
{
    Single s = 1.2345678f;
    Double d = (double) s;
    (new { s, d }).Dump();
}

По умолчанию это дает

но с кастомизированным дампом дает

Подробнее см. https://www.linqpad.net/CustomizingDump.aspx.

Вы также можете сделать это в своем запросе «Мои расширения», и это может применяться ко всем запросам.

Например. у меня что-то подобное есть в моей

public class Customisations
{        
    public static string intFormatString = null;
    public static string dateFormatString = null;
    public static string decimalFormatString = null;
    public static string doubleFormatString = null;    
}

static object ToDump(object input)
{   
    if (input is int      i  && Customisations.intFormatString     != null) return i.ToString(Customisations.intFormatString);
    if (input is decimal  de && Customisations.decimalFormatString != null) return de.ToString(Customisations.decimalFormatString);
    if (input is DateTime dt && Customisations.dateFormatString    != null) return dt.ToString(Customisations.dateFormatString);
    if (input is double   di && Customisations.doubleFormatString  != null) return di.ToString(Customisations.doubleFormatString);

    return input;
}

Так что я мог бы добавить Customisations.doubleFormatString = "#,##0.0000"; к моему запросу, чтобы сделать что-то отдаленно похожее. (Не так точно, как ваш пример, но делает то, что я хочу).

Я не уверен, что это то, что ищет кодировщик, но указатель на ToDump() - это хорошо. Вызывается ли object input, переданный в ToDump(), один раз для каждого объекта в коллекции или он применяется к свойствам объектов?

Adam Cohen 07.10.2022 10:30

@AdamCohen Он применяется ко всему, включая свойства всех объектов, которые вы выгружаете. Также вам не нужно вызывать ToDump() напрямую, вы просто используете обычную команду Dump, которая вызывает ToDump, если он существует. Следовательно, я вызываю .Dump() для объекта/таблицы, и он работает со всеми столбцами, а также если я расширяю любые ссылки на другие объекты/таблицы.

sgmoore 07.10.2022 10:46
Ответ принят как подходящий

Ответ Сгмура кажется разумным решением. Если вам нужно решение, которое можно включить в библиотеки с контролем версий, которые совместно используются вашей командой разработчиков, распространять через частные веб-каналы NuGet и т. д., один из приведенных ниже методов может быть альтернативой.

Чтобы надрать резину, вы можете вставить в файл MyExtensions и сохранить/скомпилировать его. Сделав это, вы можете использовать любой из двух приведенных ниже методов, как показано в примере использования.

Пример использования

Сохранить числовой тип данных с усечением, которое может привести к тому, что результаты Linqad будут содержать до 4 знаков после запятой (т. е. конечный 0,4400 будет выводиться как 0,44). Обратите внимание, что после преобразования все свойства типа float, double и decimal должны иметь тип double или double?.

NumericTruncate()

//supports any collection inheriting from IEnumerable<T>
var myEnumerable = new List<MyObject>();

//set precision and MidpointRounding if desired
myEnumerable.NumericTruncate(4, MidpointRounding.ToZero).Dump();

//set precision with natural rounding
myEnumerable.NumericTruncate(4).Dump();

Числовой формат()

Этот метод выводит строковые значения, отформатированные с одинаковой длиной.

//supports any collection inheriting from IEnumerable<T>
var myEnumerable = new List<MyObject>();

//set precision and MidpointRounding if desired
myEnumerable.NumericFormat(4, MidpointRounding.ToZero).Dump();

//set precision with natural rounding
myEnumerable.NumericFormat(4).Dump();

Методы MyExtensions

Вставьте приведенный ниже код в файл MyExtentions в Linqpad:


public static IEnumerable<ExpandoObject> NumericTruncate<T>(this IEnumerable<T> values, 
     int precision, MidpointRounding? round = null)
{
    var itemType = typeof(T);
    var valArr = values.ToArray();
    var types = new HashSet<Type>() { typeof(decimal), typeof(double), typeof(float) };
    var typesNullable = new HashSet<Type>() { typeof(decimal?), typeof(double?), typeof(float?) };

    var props = itemType.GetProperties(BindingFlags.Public | BindingFlags.Instance);

    for (int i = 0; i < valArr.Length; i++)
    {
        IDictionary<string, object> obj = new System.Dynamic.ExpandoObject();
        foreach (var prop in props)
        {
            var val = prop.GetValue(valArr[i]);
            if (types.Contains(prop.PropertyType))
            {
                obj[prop.Name] = round.HasValue
                    ? Math.Round(Convert.ToDouble(val), precision, round.Value)
                    : Math.Round(Convert.ToDouble(val), precision);
            }
            else if (typesNullable.Contains(prop.PropertyType))
            {
                var valNull = (double?)val;
                if (valNull.HasValue)
                    obj[prop.Name] = round.HasValue
                        ? Math.Round(Convert.ToDouble(valNull.Value), precision, round.Value)
                        : Math.Round(Convert.ToDouble(valNull.Value), precision);
                else
                    obj[prop.Name] = null;
            }
            else
                obj[prop.Name] = val;
        }
        yield return (ExpandoObject) obj;
    }
}
public static IEnumerable<ExpandoObject> NumericFormat<T>(this IEnumerable<T> values,
    int precision = 4, MidpointRounding? round = null)
{
    var itemType = typeof(T);
    var valArr = values.ToArray();
    var types = new HashSet<Type>() { typeof(decimal), typeof(double), typeof(float) };
    var typesNullable = new HashSet<Type>() { typeof(decimal?), typeof(double?), typeof(float?) };
    var pattern = "#,##0." + string.Concat(Enumerable.Range(1, precision).Select(h=> "0"));

    var props = itemType.GetProperties(BindingFlags.Public | BindingFlags.Instance);

    for (int i = 0; i < valArr.Length; i++)
    {
        IDictionary<string, object> obj = new System.Dynamic.ExpandoObject();
        foreach (var prop in props)
        {
            var val = prop.GetValue(valArr[i]);
            if (types.Contains(prop.PropertyType))
            {
                obj[prop.Name] = round.HasValue
                    ? Math.Round(Convert.ToDouble(val), precision, round.Value).ToString(pattern)
                    : Math.Round(Convert.ToDouble(val), precision).ToString(pattern);
            }
            else if (typesNullable.Contains(prop.PropertyType))
            {
                var valNull = (double?)val;
                if (valNull.HasValue)
                    obj[prop.Name] = round.HasValue
                        ? Math.Round(Convert.ToDouble(valNull.Value), precision, round.Value).ToString(pattern)
                        : Math.Round(Convert.ToDouble(valNull.Value), precision).ToString(pattern);
                else
                    obj[prop.Name] = null;
            }
            else
                obj[prop.Name] = val;
        }
        yield return (ExpandoObject)obj;
    }
}


Я не уверен, что вы неправильно поняли мой комментарий о точности, но я имел в виду, что мой ответ дал два решения, первое было точным решением, основанным на том, что запросил ОП, а второе было тем, которое я использовал, которое было менее точным, но Я использовал его, когда хотел «выровнять» свои результаты, даже ценой того, чтобы результаты выглядели более точными, чем они могут быть на самом деле.

sgmoore 07.10.2022 10:52

Другие вопросы по теме