Fcvt преобразовать double в строку с фиксированной точкой


Содержание

Преобразование вещественного числа в строку с заданной точностью

Задача Преобразовать заданное вещественное число в строку символов с указанием количества разрядов после разделителя целой и дробной части.

В продолжение темы о преобразовании целого числа в строку символов, рассмотрим вопрос преобразования в строку символов вещественного числа.

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

Функция принимает два аргумента:

  • преобразуемое число в формате double ;
  • количество знаков после запятой

Возвращаемое значение — указатель на полученную после преобразования строку.

Функции преобразования типа

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

Таблица 8.3. Преобразование данных

преобразует строку символов в число с плавающей точкой

преобразует строку символов в строку типа int

преобразует строку символов в число типа long

преобразует число с плавающей точкой типа double в строку символов; десятичная точка и знак числа не включаются в полученную строку; позиция точки и знак числа возвращаются отдельно

идентично ecvt, но округляет полученное значение до заданного числа цифр

преобразует число с плавающей точкой типа double в строку символов, включая символ десятичной точки и используя специфицированное число цифр

преобразует число типа int в строку

преобразует число типа long в строку символов

преобразует строку символов в число с плавающей точкой типа double

преобразует строку символов в число типа

преобразует строку символов в число типа

преобразует число типа unsigned long в строку символов

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

Функция atoi (), синтаксис которой

int atoi(const char* ptr)

преобразует ASCII z-строку символов, на которую указывает ptr, в число типа int. Если в строке встречается символ, который не может быть преобразован, данная функция возвращает 0. В случае если преобразуемое число превышает диапазон представления типа int. возвращается только два младших байта числа.

В отличие от нее. функция atoi () преобразует заданное строковое число в тип long. Эта функция имеет аналогичный синтаксис:

int atoi(const char* ptr)

Если преобразуемое число превышает диапазон значений типа long, функция возвратит непредсказуемое значение.

Рассмотрим пример преобразования строки цифровых символов в целое и длинное целое.

long 1 = atol (str) ;

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

Дело в том, что число 70000 в шестнадцатеричной системе счисления представляется как 0x11170, но, поскольку функция atoi() при переполнении результата возвращает только два младших байта, переменная и примет шестнадцатернчное значение 0x1170, что эквивалентно десятичному 4464. Так как atol () оперирует с четырехбайтными числами, переполнения не произойдет и переменной 1 присвоится значение 70000.

Функция atof (), определенная как

double atof(const char* ptr)

выполняет преобразование ASCllz-строки в число с плавающей точкой типа double. Строка символов должна быть представлена с учетом формата:

[пробелы] [знак] [цифры] [. ] [цифры] [e|Е [знак] цифры] ,

[пробелы] — последовательность пробелов или табуляторов; [знак] -символ ‘ + ‘ или ‘-‘: [цифры] — десятичные цифры; [е | Е ] — символ показателя степени.

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

Функции обратного преобразования itoa() и ltoa() производят конвертирование чисел типа int и long соответственно. Они имеют следующий синтаксис:

char *_ltoa(long num, char* str, int radix);

char* itoa(int num, char* str, int radix);

char* _itoa(int num, char *str, int radix);

Данные функции принимают в качестве аргумента число num и преобразуют его в строку str с учетом основания системы счисления, представленной в переменной radix. Следующий фрагмент программы преобразует целое число 98765 в строку, используя десятеричную систему счисления:

int numb = 98765; char str[10];

itoa(numb, str, 10);

cout « numb « ‘\n’ « str;

Функция strtodO преобразует строку символов в число с плавающей точкой. Ее синтаксис имеет следующий вид:

double strtod(const char *s, char **endptr);

Эта функция так же, как и функция atof О, преобразует строку, на которую указывает s, в число типа double, с тем лишь отличием, что в случае прекращения конвертирования строки возвращает указатель на первый непреобразуемый символ. Это позволяет организовать в дальнейшем обработку оставшейся части строки.

Функция gcvt () имеет прототип:

char* gcvt(double val, int ndec, char *buf);

и осуществляет конвертирование числа val типа double в ASCI I z-строку, помещая ее в буфер buf. Если число цифр, подлежащих преобразованию, меньше целого числа, указанного в ndec, в преобразованном числе указываются символы знака и десятичной точки, при этом младшие разряды дробной части отбрасываются. В противном случае число преобразуется в экспоненциальную форму, функция возвращает указатель на начало сформированной строки.

Следующий ниже пример демонстрирует использование функции gcvt () для преобразования чисел, имеющих различное представление в массивы цифровых символов.

// Обычное представление числа num = 3.547;

gcvt(num, sig, str); cout « str « ‘ \n’ ;

// Отрицательное число num = -843.7105;

gcvt(num, sig, str); cout « str « ‘\n’;

// Экспоненциальное представление num = 0.135e4;

двойное преобразование в строку с фиксированной точностью и без конечных нулей

Я должен преобразовать double значение в string , используя указанное количество цифр после точки. Однако я должен избегать печати конечных нулей, поэтому, если doubleValue равно 95 , я хочу видеть «95» а не «95.000000. » , и, аналогично, если значение равно 95.5 , я хочу видеть «95.5» а не «95.500000. » .

Это мой текущий код, использующий boost::format :

Однако он не обрабатывает два особых случая, которые я упомянул (без печати конечных нулей и без точки в случае int).

Я думаю, я могу удалить все конечные нули из строки и, наконец, удалить конечную точку, если таковые имеются.

Но я спрашиваю, есть ли более разумный способ сделать это.

Вот что я сделал:

Примечание: не обязательно использовать boost, но так как я уже использую его в своем проекте, это пригодится.

Convert. To Double Метод

Определение

Преобразует заданное значение в число с плавающей запятой двойной точности. Converts a specified value to a double-precision floating-point number.

Перегрузки

Преобразует значение заданного 8-разрядного знакового целого числа в эквивалентное число с плавающей запятой двойной точности. Converts the value of the specified 8-bit signed integer to the equivalent double-precision floating-point number.

Преобразует значение заданного объекта в число с плавающей запятой двойной точности, используя указанные сведения об особенностях форматирования, связанных с языком и региональными параметрами. Converts the value of the specified object to an double-precision floating-point number, using the specified culture-specific formatting information.

Преобразует значение заданного 64-разрядного целого числа без знака в эквивалентное число двойной точности с плавающей запятой. Converts the value of the specified 64-bit unsigned integer to an equivalent double-precision floating-point number.

Преобразует значение заданного 32-разрядного целого числа без знака в эквивалентное число двойной точности с плавающей запятой. Converts the value of the specified 32-bit unsigned integer to an equivalent double-precision floating-point number.

Преобразует значение заданного 16-разрядного целого числа без знака в эквивалентное число с плавающей запятой двойной точности. Converts the value of the specified 16-bit unsigned integer to the equivalent double-precision floating-point number.

Преобразует заданное строковое представление числа в эквивалентное число с плавающей запятой двойной точности. Converts the specified string representation of a number to an equivalent double-precision floating-point number.

Преобразует значение заданного числа с плавающей запятой одинарной точности в эквивалентное число с плавающей запятой двойной точности. Converts the value of the specified single-precision floating-point number to an equivalent double-precision floating-point number.

Преобразует заданное строковое представление числа в эквивалентное число с плавающей запятой двойной точности, используя указанные сведения об особенностях форматирования, связанных с языком и региональными параметрами. Converts the specified string representation of a number to an equivalent double-precision floating-point number, using the specified culture-specific formatting information.

Преобразует значение заданного объекта в число с плавающей запятой двойной точности. Converts the value of the specified object to a double-precision floating-point number.

Преобразует значение заданного 32-разрядного знакового целого числа в эквивалентное число с плавающей запятой двойной точности. Converts the value of the specified 32-bit signed integer to an equivalent double-precision floating-point number.

Преобразует заданное логическое значение в эквивалентное число с плавающей запятой двойной точности. Converts the specified Boolean value to the equivalent double-precision floating-point number.

Преобразует значение заданного 8-разрядного целого числа без знака в эквивалентное число с плавающей запятой двойной точности. Converts the value of the specified 8-bit unsigned integer to the equivalent double-precision floating-point number.

При вызове этого метода всегда возникает исключение InvalidCastException. Calling this method always throws InvalidCastException.

Преобразует значение заданного 64-разрядного знакового целого числа в эквивалентное число с плавающей запятой двойной точности. Converts the value of the specified 64-bit signed integer to an equivalent double-precision floating-point number.

Преобразует значение заданного десятичного числа в эквивалентное число с плавающей запятой двойной точности. Converts the value of the specified decimal number to an equivalent double-precision floating-point number.

Возвращает заданное число с плавающей запятой двойной точности; фактическое преобразование не производится. Returns the specified double-precision floating-point number; no actual conversion is performed.

Преобразует значение заданного 16-разрядного знакового целого числа в эквивалентное число с плавающей запятой двойной точности. Converts the value of the specified 16-bit signed integer to an equivalent double-precision floating-point number.

При вызове этого метода всегда возникает исключение InvalidCastException. Calling this method always throws InvalidCastException.

ToDouble(SByte)

Этот API несовместим с CLS.

Преобразует значение заданного 8-разрядного знакового целого числа в эквивалентное число с плавающей запятой двойной точности. Converts the value of the specified 8-bit signed integer to the equivalent double-precision floating-point number.

Параметры

8-разрядное целое число со знаком для преобразования. The 8-bit signed integer to convert.

Возвраты

8-разрядное целое число со знаком, которое эквивалентно значению value . The 8-bit signed integer that is equivalent to value .

Примеры

В следующем примере каждый элемент массива SByte значений преобразуется Double в значение. The following example converts each element in an array of SByte values to a Double value.

ToDouble(Object, IFormatProvider)

Преобразует значение заданного объекта в число с плавающей запятой двойной точности, используя указанные сведения об особенностях форматирования, связанных с языком и региональными параметрами. Converts the value of the specified object to an double-precision floating-point number, using the specified culture-specific formatting information.

Параметры


Объект, реализующий интерфейс IConvertible. An object that implements the IConvertible interface.

Объект, предоставляющий сведения о форматировании для определенного языка и региональных параметров. An object that supplies culture-specific formatting information.

Возвраты

Число с плавающей запятой двойной точности, эквивалентное значению value , или нуль, если value имеет значение null . A double-precision floating-point number that is equivalent to value , or zero if value is null .

Исключения

value имеет неправильный формат для типа Double. value is not in an appropriate format for a Double type.

value не реализует интерфейс IConvertible. value does not implement the IConvertible interface.

Параметр value представляет число меньше MinValue или больше MaxValue. value represents a number that is less than MinValue or greater than MaxValue.

Примеры

В следующем примере определяется класс, реализующий IConvertible интерфейс, и класс, IFormatProviderреализующий интерфейс. The following example defines a class that implements IConvertible and a class that implements IFormatProvider. Объекты класса, реализующего IConvertible , содержат Double массив значений. Objects of the class that implements IConvertible hold an array of Double values. Объект каждого класса передается ToDouble в метод. An object of each class is passed to the ToDouble method. Этот метод возвращает среднее значение массива Double значений с помощью объекта, реализующего IFormatProvider метод, чтобы определить, как вычисляется среднее значение. This method returns an average of the array of Double values, using the object that implements IFormatProvider to determine how to calculate the average.

Комментарии

Возвращаемое значение является результатом вызова IConvertible.ToDouble метода базового value типа. The return value is the result of invoking the IConvertible.ToDouble method of the underlying type of value .

provider позволяет пользователю указать сведения о преобразовании для value содержимого в зависимости от языка и региональных параметров. provider enables the user to specify culture-specific conversion information about the contents of value . Например, если value String параметр имеет значение, представляющее число, provider может предоставить сведения об нотации, используемой для представления этого числа, в зависимости от языка и региональных параметров. For example, if value is a String that represents a number, provider could supply culture-specific information about the notation used to represent that number.

Базовые типы игнорируются provider ; однако параметр может использоваться, если value является IConvertible определяемым пользователем типом, реализующим интерфейс. The base types ignore provider ; however, the parameter may be used if value is a user-defined type that implements the IConvertible interface.

ToDouble(UInt64)

Этот API несовместим с CLS.

Преобразует значение заданного 64-разрядного целого числа без знака в эквивалентное число двойной точности с плавающей запятой. Converts the value of the specified 64-bit unsigned integer to an equivalent double-precision floating-point number.

Параметры

64-разрядное целое число без знака для преобразования. The 64-bit unsigned integer to convert.

Возвраты

Число с плавающей запятой двойной точности, которое эквивалентно значению value . A double-precision floating-point number that is equivalent to value .

Примеры

В следующем примере каждый элемент массива UInt64 значений преобразуется Double в значение. The following example converts each element in an array of UInt64 values to a Double value.

ToDouble(UInt32)

Этот API несовместим с CLS.

Преобразует значение заданного 32-разрядного целого числа без знака в эквивалентное число двойной точности с плавающей запятой. Converts the value of the specified 32-bit unsigned integer to an equivalent double-precision floating-point number.

Параметры

32-разрядное целое число без знака для преобразования. The 32-bit unsigned integer to convert.

Возвраты

Число с плавающей запятой двойной точности, которое эквивалентно значению value . A double-precision floating-point number that is equivalent to value .

Примеры

В следующем примере каждый элемент массива UInt32 значений преобразуется Double в значение. The following example converts each element in an array of UInt32 values to a Double value.

ToDouble(UInt16)

Этот API несовместим с CLS.

Преобразует значение заданного 16-разрядного целого числа без знака в эквивалентное число с плавающей запятой двойной точности. Converts the value of the specified 16-bit unsigned integer to the equivalent double-precision floating-point number.

Параметры

16-разрядное целое число без знака для преобразования. The 16-bit unsigned integer to convert.

Возвраты

Число с плавающей запятой двойной точности, которое эквивалентно значению value . A double-precision floating-point number that is equivalent to value .

Примеры

В следующем примере каждый элемент массива UInt16 значений преобразуется Double в значение. The following example converts each element in an array of UInt16 values to a Double value.

ToDouble(String)

Преобразует заданное строковое представление числа в эквивалентное число с плавающей запятой двойной точности. Converts the specified string representation of a number to an equivalent double-precision floating-point number.

Параметры

Строка, содержащая преобразуемое число. A string that contains the number to convert.

Возвраты

Число с плавающей запятой двойной точности, эквивалентное числу value , или 0 (нуль), если value имеет значение null . A double-precision floating-point number that is equivalent to the number in value , or 0 (zero) if value is null .

Исключения

value не является числом в допустимом формате. value is not a number in a valid format.

Параметр value представляет число меньше MinValue или больше MaxValue. value represents a number that is less than MinValue or greater than MaxValue.

Примеры

В следующем примере предпринимается попытка преобразовать каждый элемент массива числовых строк в Double. The following example attempts to convert each element in an array of numeric strings to a Double. В качестве выходных данных примера используется система, текущая культура которой — en-US. The example’s output is from a system whose current culture is en-US.

Комментарии

Использование метода эквивалентно передаче value в Double.Parse(String) метод. ToDouble(String) Using the ToDouble(String) method is equivalent to passing value to the Double.Parse(String) method. Параметр value интерпретируется с использованием соглашений о форматировании, принятых в культуре текущего потока. value is interpreted by using the formatting conventions of the current thread culture.

Если вы предпочитаете не выполнять обработку исключения в случае сбоя преобразования, можно вызвать Double.TryParse метод. If you prefer not to handle an exception if the conversion fails, you can call the Double.TryParse method instead. Он возвращает Boolean значение, указывающее, успешно ли выполнено преобразование. It returns a Boolean value that indicates whether the conversion succeeded or failed.

ToDouble(Single)

Преобразует значение заданного числа с плавающей запятой одинарной точности в эквивалентное число с плавающей запятой двойной точности. Converts the value of the specified single-precision floating-point number to an equivalent double-precision floating-point number.

Параметры

Число с плавающей запятой одиночной точности. The single-precision floating-point number.

Возвраты

Число с плавающей запятой двойной точности, которое эквивалентно значению value . A double-precision floating-point number that is equivalent to value .

Примеры

В следующем примере Single значение преобразуется Double в значение. The following example converts a Single value to a Double value.

Дополнительно

ToDouble(String, IFormatProvider)

Преобразует заданное строковое представление числа в эквивалентное число с плавающей запятой двойной точности, используя указанные сведения об особенностях форматирования, связанных с языком и региональными параметрами. Converts the specified string representation of a number to an equivalent double-precision floating-point number, using the specified culture-specific formatting information.

Параметры

Строка, содержащая преобразуемое число. A string that contains the number to convert.

Объект, предоставляющий сведения о форматировании для определенного языка и региональных параметров. An object that supplies culture-specific formatting information.

Возвраты

Число с плавающей запятой двойной точности, эквивалентное числу value , или 0 (нуль), если value имеет значение null . A double-precision floating-point number that is equivalent to the number in value , or 0 (zero) if value is null .

Исключения

value не является числом в допустимом формате. value is not a number in a valid format.

Параметр value представляет число меньше MinValue или больше MaxValue. value represents a number that is less than MinValue or greater than MaxValue.

Примеры

В следующем примере строковые представления Double значений ToDouble преобразуются в метод с помощью IFormatProvider объекта. The following example converts string representations of Double values with the ToDouble method, using an IFormatProvider object.

Комментарии

Возвращаемое значение является результатом вызова Double.Parse метода для. value The return value is the result of invoking the Double.Parse method on value .

provider NumberFormatInfo — это IFormatProvider экземпляр, который получает объект. provider is an IFormatProvider instance that obtains a NumberFormatInfo object. Объект предоставляет сведения о формате для value конкретного языка и региональных параметров. NumberFormatInfo The NumberFormatInfo object provides culture-specific information about the format of value . Если provider имеет null значение ,NumberFormatInfo используется для текущего языка и региональных параметров. If provider is null , the NumberFormatInfo for the current culture is used.

Если вы предпочитаете не выполнять обработку исключения в случае сбоя преобразования, можно вызвать Double.TryParse метод. If you prefer not to handle an exception if the conversion fails, you can call the Double.TryParse method instead. Он возвращает Boolean значение, указывающее, успешно ли выполнено преобразование. It returns a Boolean value that indicates whether the conversion succeeded or failed.

ToDouble(Object)

Преобразует значение заданного объекта в число с плавающей запятой двойной точности. Converts the value of the specified object to a double-precision floating-point number.

Параметры

Объект, реализующий интерфейс IConvertible, или значение null . An object that implements the IConvertible interface, or null .

Возвраты

Число с плавающей запятой двойной точности, эквивалентное значению value , или нуль, если value имеет значение null . A double-precision floating-point number that is equivalent to value , or zero if value is null .

Исключения

value имеет неправильный формат для типа Double. value is not in an appropriate format for a Double type.

value не реализует интерфейс IConvertible. value does not implement the IConvertible interface.

-или- -or- Преобразование не поддерживается. The conversion is not supported.

Параметр value представляет число меньше MinValue или больше MaxValue. value represents a number that is less than MinValue or greater than MaxValue.

Примеры

В следующем примере предпринимается попытка преобразовать каждое значение в массиве Doubleобъектов в. The following example attempts to convert each value in an object array to a Double.

Комментарии

Если value IConvertible.ToDouble value параметр не равен ,этотметодсоздаетоболочкувызовадляреализациибазовоготипа. null If value is not null , this method wraps a call to the IConvertible.ToDouble implementation of the underlying type of value .

ToDouble(Int32)

Преобразует значение заданного 32-разрядного знакового целого числа в эквивалентное число с плавающей запятой двойной точности. Converts the value of the specified 32-bit signed integer to an equivalent double-precision floating-point number.

Параметры

32-разрядное целое число со знаком для преобразования. The 32-bit signed integer to convert.

Возвраты

Число с плавающей запятой двойной точности, которое эквивалентно значению value . A double-precision floating-point number that is equivalent to value .

Примеры


В следующем примере Int32 значение преобразуется Double в значение. The following example converts an Int32 value to a Double value.

ToDouble(Boolean)

Преобразует заданное логическое значение в эквивалентное число с плавающей запятой двойной точности. Converts the specified Boolean value to the equivalent double-precision floating-point number.

Параметры

Логическое значение, которое необходимо преобразовать. The Boolean value to convert.

Возвраты

Число 1, если value имеет значение true ; в противном случае — 0. The number 1 if value is true ; otherwise, 0.

Примеры

В следующем примере Boolean значение преобразуется Double в значение. The following example converts a Boolean value to a Double value.

ToDouble(Byte)

Преобразует значение заданного 8-разрядного целого числа без знака в эквивалентное число с плавающей запятой двойной точности. Converts the value of the specified 8-bit unsigned integer to the equivalent double-precision floating-point number.

Параметры

8-разрядное целое число без знака для преобразования. The 8-bit unsigned integer to convert.

Возвраты

Число с плавающей запятой двойной точности, которое эквивалентно значению value . The double-precision floating-point number that is equivalent to value .

Примеры

В следующем примере Byte значение преобразуется Double в значение. The following example converts a Byte value to a Double value.

ToDouble(Char)

При вызове этого метода всегда возникает исключение InvalidCastException. Calling this method always throws InvalidCastException.

Параметры

Знак Юникода, который необходимо преобразовать. The Unicode character to convert.

Возвраты

Данное преобразование не поддерживается. This conversion is not supported. Возвращаемое значение отсутствует. No value is returned.

Исключения

Данное преобразование не поддерживается. This conversion is not supported.

Дополнительно

ToDouble(Int64)

Преобразует значение заданного 64-разрядного знакового целого числа в эквивалентное число с плавающей запятой двойной точности. Converts the value of the specified 64-bit signed integer to an equivalent double-precision floating-point number.

Параметры

64-разрядное целое число со знаком для преобразования. The 64-bit signed integer to convert.

Возвраты

Число с плавающей запятой двойной точности, которое эквивалентно значению value . A double-precision floating-point number that is equivalent to value .

Примеры

В следующем примере каждый элемент массива длинных целых чисел Double со знаком преобразуется в значение. The following example converts each element in an array of signed long integers to a Double value.

ToDouble(Decimal)

Преобразует значение заданного десятичного числа в эквивалентное число с плавающей запятой двойной точности. Converts the value of the specified decimal number to an equivalent double-precision floating-point number.

Илон Маск рекомендует:  Опции ввода

Параметры

Десятичное число для преобразования. The decimal number to convert.

Возвраты

Число с плавающей запятой двойной точности, которое эквивалентно значению value . A double-precision floating-point number that is equivalent to value .

Примеры

В следующем примере Decimal значение преобразуется Double в значение. The following example converts a Decimal value to a Double value.

ToDouble(Double)

Возвращает заданное число с плавающей запятой двойной точности; фактическое преобразование не производится. Returns the specified double-precision floating-point number; no actual conversion is performed.

Параметры

Возвращаемое число с плавающей запятой двойной точности. The double-precision floating-point number to return.

Возвраты

value возвращается без изменений. value is returned unchanged.

Дополнительно

ToDouble(Int16)

Преобразует значение заданного 16-разрядного знакового целого числа в эквивалентное число с плавающей запятой двойной точности. Converts the value of the specified 16-bit signed integer to an equivalent double-precision floating-point number.

Параметры

16-разрядное целое число со знаком для преобразования. The 16-bit signed integer to convert.

Возвраты

Число с плавающей запятой двойной точности, эквивалентное значению value . A double-precision floating-point number equivalent to value .

Примеры

В следующем примере каждый элемент массива из 16-разрядных целых чисел со знаком преобразуется в Double значение. The following example converts each element in an array of 16-bit signed integers to a Double value.

ToDouble(DateTime)

При вызове этого метода всегда возникает исключение InvalidCastException. Calling this method always throws InvalidCastException.

Параметры

Значение даты и времени для преобразования. The date and time value to convert.

Возвраты

Данное преобразование не поддерживается. This conversion is not supported. Возвращаемое значение отсутствует. No value is returned.

Исключения

Данное преобразование не поддерживается. This conversion is not supported.

Fcvt преобразовать double в строку с фиксированной точкой

Преобразование типов данных, это приведение одного типа к другому. Например, приведение целочисленной переменной к числу с плавающей точной, или преобразование числа в строку. В C# выделяют два варианта преобразования типов:

  • Неявное преобразование типов. Это, так называемое безопасное преобразование типов в C#. Например, преобразование из типа float (более «маленький» тип) в тип double (более «большой» тип). При таком преобразовании никакая информация не «потеряется», что при обратном преобразовании вполне возможно.
  • Явное преобразование типов. Такое преобразование выполняется программистом с прямым указанием типа, к которому нужно привести переменную. Для такого преобразования требуется наличие оператора преобразования.

А теперь, я покажу как можно использовать явное преобразование типов в C#:

Преобразование типа double в тип int выполнялось в выделенной строке (строке с номером 16). Если вы соберете данный пример и запустите его, то увидите, что преобразование типов прошло, т.е. из числа с плавающей точкой мы получили целое число.

Так же, для преобразования данных из одного типа в другой, есть целый класс с именем Convert, у которого имеются специальные методы. Ниже, в таблице, представлены основные методы этого класса.


Цитата(feodorv @ 16.8.2015, 17:03 )
Дело Ваше. У Вас какая-то патологическая нелюбовь к стандартным решениям, что к стандартной библиотеке, что к printf. Разубеждать Вас не буду.

До стандартной библиотеки я просто ещё не добрался. А printf не люблю не только я. И она не стандартная, а устаревшая.

Это сообщение отредактировал(а) TarasProger — 16.8.2015, 19:28

Профиль
Группа: Участник
Сообщений: 210
Регистрация: 28.11.2011

Репутация: нет
Всего: 3

disputant
Дата 16.8.2015, 21:36 (ссылка) | (голосов:1) Загрузка .
Цитата(feodorv @ 16.8.2015, 15:06)
Лучшее из всех решений, на мой взгляд (как ни крути), это всё-таки использование функций семейства printf.

Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 11
Всего: 45

feodorv
Дата 16.8.2015, 21:39 (ссылка) | (нет голосов) Загрузка .

Профиль
Группа: Участник
Сообщений: 104
Регистрация: 5.8.2015

Репутация: нет
Всего: нет

TarasProger
Дата 17.8.2015, 07:33 (ссылка) | (нет голосов) Загрузка .
Цитата(feodorv @ 16.8.2015, 21:39 )
Уж лучше использовать _ecvt_s

И чем же оно лучше стандартного решения? ООП-ного, надёжного и безопасного.

Добавлено @ 07:47
disputant, а как задать точность преобразования и заставить его выводить не значащие ноли в конце?

Код
Buffer.precision(8);
Buffer >Result;
return Result;

не помогает. Buffer.precision(2);
Buffer >Result;
return Result;[/code] точность ограничивает, Value=3.14, результат 3.1, но Buffer.precision(8);
Buffer >Result;
return Result;[/code] выводит 3.14 вместо 3.1400000. Как задать разделитель целой и дробной части?

Это сообщение отредактировал(а) TarasProger — 17.8.2015, 07:56

Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 11
Всего: 45

feodorv
Дата 17.8.2015, 12:32 (ссылка) | (нет голосов) Загрузка .
Цитата(TarasProger @ 17.8.2015, 07:33 )
И чем же оно лучше стандартного решения?

Профиль
Группа: Участник
Сообщений: 338
Регистрация: 21.2.2009
Где: Балашиха или Воро неж

Репутация: нет
Всего: 4

Курсант
Дата 17.8.2015, 16:22 (ссылка) | (голосов:1) Загрузка .
Цитата(TarasProger @ 17.8.2015, 07:33)
Цитата(feodorv @ 16.8.2015, 21:39 )
Уж лучше использовать _ecvt_s

И чем же оно лучше стандартного решения? ООП-ного, надёжного и безопасного.

Добавлено @ 07:47
disputant, а как задать точность преобразования и заставить его выводить не значащие ноли в конце?

Код
Buffer.precision(8);
Buffer >Result;
return Result;

не помогает. Buffer.precision(2);
Buffer >Result;
return Result;[/code] точность ограничивает, Value=3.14, результат 3.1, но Buffer.precision(8);
Buffer >Result;
return Result;[/code] выводит 3.14 вместо 3.1400000. Как задать разделитель целой и дробной части?

Уважаемый TarasProger, мне очень нравится Ваш стиль программирования, в нём чувствуется будущий хороший специалист. Хотя и заметно, что программирование является для Вас чем-то новым, Вы отлично улавливаете суть, у Вас есть творческая струнка, которая звенит, и это здорово. Но.

Примите к сведению, что сейчас у Вас необходимый этап развития — изобретение велосипедов на квадратных колёсах. Хотя колёса у Ваших велосипедов не такие уж и квадратные. На мой взгляд, это лучше, чем бездумное использование чужих решений. Главное — не перегнуть палку в этом вопросе, изучать стандартные решения, использовать их. Если разные библиотеки типа Qt или WxWidgets — это ещё спорный момент, то такие вещи как STL (стандартная библиотека шаблонов С++), WinAPI (не уверен что злободневно) и .NET — это то, чем нужно пользоваться. Это системы с очень изящной структурой, даже поверхностное знакомство с ними учит организовывать работу сложных программ.

То есть те ответы, которые Вам дают — они отличные, если говорить строго технически. Есть отличный принцип в конструировании — меньше изобретать и больше конструировать. Нужно стараться максимально агрегатировать уже написанные функции из стандартных библиотек. Они, во-первых, избавлены от ошибок многочисленными прогонами и частым использованием, во-вторых, экономят время при разработке ПО, в третьих, упрощают поддержку Ваших программ другими разработчиками, которые знакомы со стандартными решениями, и не знакомы с Вашими решениями.

НО, повторюсь, то, что Вы делаете, т.е. изобретение своих библиотек — это, на мой взгляд, необходимый этап. Более того, уверен, большая часть людей, рекомендующих Вам использовать стандартные решения, сама прошла через такое вот изобретение велосипедов. Неважно в каком возрасте. Это позволяет отточить алгоритмическое мышление.

Лично я Ваши посты читаю с удовольствием, хотя и понимаю, что нужно использовать стандартные механизмы. Наверное стоит сделать отдельную ветку на форуме — «изобретаем велосипед», где молодые горячие программисты будут выкладывать свой код, а опытные будут показывать, как лучше в таких случаях использовать стандартные решения. Это будет полезно всем — и опытным разработчикам (вспомнить, как писать низкоуровневые функции), и молодым (понять, как использовать стандартные решения).

Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 37
Всего: 85

volatile
Дата 17.8.2015, 20:45 (ссылка) | (нет голосов) Загрузка .
Цитата(Курсант @ 17.8.2015, 16:22 )
необходимый этап развития — изобретение велосипедов на квадратных колёсах.

Да всё замечательно, если бы только он не внушал «городу и миру», что только велосипеды с квадратными колесами являются правильными.

Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 37
Всего: 85

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

Ну а вообще это холивар.

volatile
Дата 17.8.2015, 21:06 (ссылка) | (голосов:1) Загрузка .

Профиль
Группа: Админ
Сообщений: 11740
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 12
Всего: 459

Alexeis
Дата 18.8.2015, 01:06 (ссылка) | (нет голосов) Загрузка .
Цитата(volatile @ 17.8.2015, 22:06 )
по удобству использования и эффективности полученного кода, она даст мноооого очков вперед форы выводу в stringstream и иже с ними.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать

Профиль
Группа: Участник
Сообщений: 210
Регистрация: 28.11.2011

Описание функций языка Си

All | _ | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z

strtod – преобразование строки в число типа double.

#include
double strtod (const char *str, char **endstr);

str – указатель на строку для преобразования.
endstr – указатель на переменную, в которую будет помещен указатель на непреобразованный остаток строки или на начало строки str, если преобразование не удалось или вся строка преобразована.

При успешном завершении функции возвращается результат преобразования – число типа double, а по адресу указанному в переменной endstr записывается указатель на оставшуюся непреобразованную часть строки или указатель на начало строки, если вся строка была преобразована.

Если преобразование не может быть выполнено, то возвращается 0, а по адресу указанному в переменной endstr записывается указатель на начало строки str.

Если в результате преобразования получено слишком большое по абсолютной величине число, то будет возвращено плюс или минус HUGE_VAL в зависимости от знака числа и переменной errno будет присвоено значение [ERANGE]. Если получено слишком маленькое по абсолютной величине число, то будет возвращен 0 и переменной errno будет присвоено значение [ERANGE]. При этом по адресу указанному в переменной endstr записывается указатель на оставшуюся непреобразованную часть строки или указатель на начало строки, если вся строка была преобразована.

Функция преобразует строку (с числом с плавающей точкой) в число типа double. Число с плавающей точкой — форма представления действительных чисел, в которой число хранится в форме мантиссы и показателя степени, например 123.45*e6, где 123.45 – мантисса, 6 – порядок.

Преобразуемая строка должна иметь вид: [pr] [zn] [dс] [.] [dd] [e[znp]dp]

[pr] – пробел. В начале преобразуемой строки пробел необязателен. Если в одной строке содержится несколько чисел в символьном формате, то они должны быть разделены пробелами.

[zn] – знак мантиссы + или — , если знак отсутствует, то мантисса считается положительной.

[dс] – десятичные цифры целой части мантиссы, если данные цифры отсутствует, то целая часть мантиссы считается нулевой.

[.] – десятичная точка (разделитель целой и дробной части мантиссы), если данный знак отсутствует, то мантисса содержит только целую часть.

[dd] — десятичные цифры дробной части мантиссы, если данные числа отсутствуют, то мантисса содержит только целую часть.

[e] – символ e или E, если данный символ отсутствует, то число с плавабющей точкой не содержит порядок (содержит нулевой порядок).

[znp] – знак порядка + или — , если знак отсутствует, то порядок считается положительным.

[dp] – десятичные цифры порядка, если цифры отсутствуют порядок равен 0.

Наличие либо целой, либо дробной части числа мантиссы обязательно, порядок может полностью отсутствовать, но если он указан, обязательно перед порядком должен идти символ e или E. Пробелы внутри числа с плавающей точкой недопустимы.

Примеры записи числа с плавающей точкой: +123.45e6, +123.45E6, 123E-6, -123E6, -.45e6, +123.45 и т.д.

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

В примере строка «+123.45e6 +123.45E6 0 123E-6 -123E6 -.45e6 +123.45» преобразуется в семь чисел типа double и результат выводится на консоль.

Вывод в консоль:

disputant
Дата 19.8.2015, 20:30 (ссылка) | (нет голосов) Загрузка .

123450000.000000
123450000.000000
0.000000
0.000123
-123000000.000000
-450000.000000
123.450000

Fcvt преобразовать double в строку с фиксированной точкой

В этом документе (перевод раздела «Using Native Fixed-Point Types» документации [1]) предоставлен обзор поддержки компилятором VisualDSP традиционных типов с фиксированной точкой (native fixed-point types) fract и accum, как это определено в Главе 4 «Extensions to support embedded processors» ISO/IEC draft document Technical Report 18037.

[Поддержка типов с фиксированной точкой]

Тип данных с фиксированной точкой это такой тип, у которого точка основания, разделяющая целую и дробную части, находится в фиксированной позиции внутри бит двоичного числа заданной разрядности. Это включает целые типы (точка находится непосредственно справа от самого младшего значащего бита числа). Однако в здесь используется термин «фиксированная точка» только к тем случаям представления дробных чисел, когда под дробную часть выделено не нулевое количество бит числа, т. е. есть в наличии биты, стоящие справа после точки. Могут быть также биты под целую часть числа, стоящие слева от точки.

У процессора Blackfin имеется встроенная аппаратная поддержка для арифметики на числах с такими типами данных, имеющих фиксированную точку. Например, процессор может выполнять сложение, вычитание и умножение на 16-битных и 32-битных дробных значениях. Однако язык C не предусматривает простого расширения семантики арифметики, которая позволит использовать поддержку нижележащей аппаратуры.

Чтобы упростить использование этой аппаратной возможности и применить расширение языка для алгоритмов DSP, которые манипулируют типами с фиксированной точкой, компилятор поддерживает набор типов native fixed-point, арифметика которых подчиняется семантике чисел с фиксированной точкой. Это упрощает написание высокопроизводительных алгоритмов для манипуляции данными с фиксированной точкой, без необходимости обращаться к встроенным функциям компилятора (compiler built-ins), или встраиваемому коду на языке ассемблера (inline assembly).

Появление стандарта для таких типов с плавающей точкой установлено в Главе 4 «Extensions to support embedded processors» ISO/IEC Technical Report 18037. VisualDSP++ предоставляет всю функциональность, обозначенную в этой главе, и эта глава является полезным справочником, объясняющим тонкости семантики библиотечных функций и арифметических операторов. Однако в следующих секциях дается обзор этих типов данных, семантики арифметики использования этих типов, и руководства о том, как писать высокопроизводительный код с использованием этих типов.

Традиционные типы с плавающей точкой (Native Fixed-Point Types). Два ключевых слова, _Fract и _Accum, используются для декларирования переменных, имеющих тип с фиксированной точкой. Каждое из этих ключевых слова может быть также использовано совместно со спецификаторами типа short и long, а также signed и unsigned. Таким образом, имеется 12 доступных типов с плавающей точкой, хотя некоторые из них являются псевдонимами для типов, имеющих такой же размер и формат.

Путем подключения заголовочного файла stdfix.h можно использовать более удобный синтаксис — fract и accum вместо _Fract и _Accum. Заголовочный файл stdfix.h также предоставляет прототипы многих полезных функций, и весьма рекомендуется подключать его в файлы исходного кода, которые используют типы с фиксированной точкой. Таким образом вся дискуссия, которая пойдет дальше, будет использовать семантику с ключевыми словами fract и accum, как это делает остальная часть документации VisualDSP++.

Форматы типов с фиксированной точкой даны в таблице 1-15. В столбце «Представление» таблицы число после точки показывает количество бит, отведенное под дробную часть, в то время как число слева от точки означает количество бит целой части числа, включая бит знака, который обозначается буквой s. Типы со знаком (signed) используют форму представления чисел с дополнением до 2 (как обычные числа со знаком). Также в этой таблице представлен диапазон значений, которые могут принимать эти числа. Обратите внимание, что нижнее значение диапазона указано включительно (обозначено квадратной скобкой), в то время как верхнее значение диапазона указано исключительно (т. е. не включая, что обозначено круглой скобкой). Таким образом, для положительного верхнего предела значений может быть представлено значение только на вес 1 бита меньше, чем указанное.

Таблица 1-15. Форматы хранения, диапазоны и размеры типов Native Fixed-Point.

Тип Представление Диапазон sizeof
short fract s1.15 [-1.0,1.0) 2
fract
long fract s1.31 4
unsigned short fract 0.16 [0.0,1.0) 2
unsigned fract
unsigned long fract 0.32 4
short accum s9.31 [-256.0,256.0) 8
accum
long accum
unsigned short accum 8.32 [0.0,256.0)
unsigned accum
unsigned long accum

Стандарт (Technical Report 18037) также определяет ключевое слово _Sat для квалификатора типа с фиксированной точкой (альтернативное, более удобное представление sat). Это предусматривает, что вся арифметика над переменной fixed-point с таким квалификатором должна использовать арифметику с насыщением, т. е. в случае переполнения результата арифметических операций число останется в виде самого максимального (или самого минимального) значения, которое может представить тип. Когда квалификатор sat не используется, стандарт говорит, что арифметические операции могут допускать переполнение, которое будет вести себя неопределенным (с точки зрения стандарта) образом, т. е. будет зависеть от платформы, на которой работает код. VisualDSP++ принимает квалификатор sat для совместимости, но будет всегда генерировать код, который будет насыщать результат операции независимо от того, был использован квалификатор sat или нет. Это дает максимальную воспроизводимость результатов и позволяет писать код, не беспокоясь о неожиданных эффектах переполнения.

Традиционные константы с фиксированной точкой (Native Fixed-Point Constants). Константы с фиксированной точкой могут быть заданы в том же формате, что и константы с плавающей точкой, включая любую десятичную или бинарную экспоненту. Для дополнительной информации об этих форматах см. врезку с описанием функции strtofxfx.

Для идентификации типа констант используются суффиксы. Заголовочный файл stdfix.h также декларирует макросы для максимальных и минимальных значений типов с фиксированной точкой. См. таблицу 1-16 для подробного описания суффиксов и максимальных и минимальных значений соответствующих типов с фиксированной точкой.

Таблица 1-16. Суффиксы и макросы для констант типа с фиксированной точкой.

Тип Суффикс Пример Min Max
short fract hr 0.5hr SFRACT_MIN SFRACT_MAX
fract r 0.5r FRACT_MIN FRACT_MAX
long fract lr 0.5lr LFRACT_MIN LFRACT_MAX
unsigned short fract uhr 0.5uhr 0.0uhr USFRACT_MAX
unsigned fract ur 0.5ur 0.0ur UFRACT_MAX
unsigned long fract ulr 0.5ulr 0.0ulr ULFRACT_MAX
short accum hk 12.4hk SACCUM_MIN SACCUM_MAX
accum k 12.4k ACCUM_MIN ACCUM_MAX
long accum lk 12.4lk LACCUM_MIN LACCUM_MAX
unsigned short accum uhk 12.4uhk 0.0uhk USACCUM_MAX
unsigned accum uk 12.4uk 0.0uk UACCUM_MAX
unsigned long accum ulk 12.4ulk 0.0ulk ULACCUM_MAX

[Мотивирующий пример]

Рассмотрим очень простой пример операции скалярного умножения (dot-product) с фиксированной точкой. Как бы Вы написали подобное с использованием традиционных типов с фиксированной точкой? Алгоритм выполняет умножение каждой пары дробных значений во входных массивах. Тип accum разработан для хранения результатов накопления, что является именно тем, что нужно. Предположим, что данные состоят из векторов 16-битных значений в диапазоне [-1.0,1.0). Тогда естественно написать следующее:

Этот показанный выше алгоритм выполняет попарное умножение элементов входных массивов и накапливает результат в переменной, которая получит насыщение при переполнении. Фактически это простое расширение алгоритма скрывает тонкость, связанную с семантикой арифметики, что обсуждается во врезке FX_CONTRACT, но оно показывает, как можно просто расширять алгоритмы, которые манипулируют данными с фиксированной точкой и выполняют насыщение результата при переполнении, без необходимости поиска специальных путей для расширения этих семантик через целочисленную арифметику.

[Семантика арифметики с фиксированной точкой]

Семантики арифметики с фиксированной точкой, работающие в соответствии с вышеупомянутым Technical Report, следующие:

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


2. Если в операторе имеется два операнда с фиксированной точкой, но с разным отношением к знаковости (т. е. один операнд signed, другой unsigned), то тогда операнд unsigned переводится в signed без изменения размерности (однако также см. FX_CONTRACT).

3. Выведение типа результата оператора. Результатом типа будет тип операнда с самым высоким рангом. Ранг увеличивается в следующем порядке: short fract, fract, long fract, short accum, accum, long accum (или их unsigned эквиваленты). Оператор, у которого только один операнд типа fixed-point, даст результат типа fixed-point (исключение составляет оператор сравнения, который даст результат boolean).

4. Математический результат, который получается от действия оператора над значениями операндов, преобразуется в тот тип результата, который определен на шаге 3. Другими словами, результат будет как если бы он был вычислен с бесконечной точностью перед тем, как преобразовать его в тип для конечного результата.

Преобразования между различными типами обсуждаются в секции «Преобразования типов данных и типы с фиксированной точкой».

[Преобразования типов данных и типы с фиксированной точкой]

Правила преобразования в тип с фиксированной точкой и из этого типа следующие:

1. Когда происходит преобразование в тип с фиксированной точкой, то если значение операнда может быть представлено типом с фиксированной точкой, то результат получит это значение. Если значение операнда выходит за диапазон типа с фиксированной точкой, то результат будет ближайшее значение операнда для этого типа с фиксированной точкой. Другими словами, преобразование к типу с фиксированной точкой приведет к насыщению математического значения операнда до диапазона значений типа с фиксированной точкой. Если значение операнда находится в диапазоне типа с фиксированной точкой, но не может быть представлено точно, то результат получит ближайшее значение либо к самому большому, либо самому малому значению операнда. Для дополнительной информации см. «Поведение округления».

2. Когда происходит преобразование в целый тип из числа с фиксированной точкой, то результатом будет целая часть от типа с фиксированной точкой. Дробная часть будет отброшена, как при округлении по направлению к 0; (int)(1.9k) даст 1, и (int)(-1.9k) даст -1.

3. Когда происходит преобразование типа с фиксированной точкой к типу с плавающей точкой, то результат получит ближайшее к значению операнда значение с плавающей точкой.

У этих правил есть важные последствия, которые Вы должны учитывать:

1. Преобразование целого числа в дробное полезно только если целое число равно -1, 0 или 1. Все другие целые значения получат насыщение к дробному типу. Так что оператор наподобие:

вовсе не присвоит 0.5 переменной f, но вместо этого f получит значение FRACT_MAX, потому что 0x4000 это целое число, большее 1. Вместо этого используйте:

Обратите внимание, что второй рекомендуемый пример использует синтаксис двоичной экспоненты, доступный для констант с фиксированной точкой; т. е. в данном примере значение 0x4000 масштабируется на 2 -15 .

2. Присваивание дробного значения целому приведет к нулю, кроме случая, когда дробное значение равно -1.0. Присваивание беззнакового дробного значения целому всегда даст в результате 0.

3. Будьте очень осторожны, чтобы случайно не перепутать типы fract16 и fract32 с fract и long fract. Типы fract16 и fract32 это не подлинные дробные типы, это просто typedef-ы от целочисленных типов данных. Так, например:

По той причине, что f16 это целое число, произойдет насыщение при присвоении его к истинно дробному типу. Компилятор выдаст ошибку, когда он может детектировать, что fract16 или fract32 были сконвертированы в тип fract или long fract (или было обратное преобразование), потому что это почти всегда означает ошибку программирования. Для преобразования между целочисленными typedef-ами и традиционными типами используйте функции преобразования bitsfx и fxbitss.

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

[Функции преобразования полей бит bitsfx и fxbitss]

Заголовочный файл stdfix.h предоставляет функции для преобразования полей бит в тип с фиксированной точкой и обратно. В частности, эти функции полезны для преобразования между традиционными дробными типами (fract, long fract) и целочисленными typedef-ами (fract16, fract32).

Для каждого типа с фиксированной точкой декларирован соответствующий целочисленный тип, который содержит достаточное количество бит, чтобы удержать в себе информацию типа с фиксированной точкой. Это типы int_fx_t, где fx заменяется на одно из сочетаний hr, r, lr, hk, k или lk, и uint_fx_t, где fx заменяется на одно из сочетаний uhr, ur, ulr, uhk, uk или ulk.

Чтобы преобразовать тип с точкой дробного числа в поле бит, используйте семейство функций bitsfx. fx может быть любым из сочетаний hr, r, lr, hk, k, lk, uhr, ur, ulr, uhk, uk или ulk. Например, с использованием прототипа

Вы можете написать:

Это хороший способ для преобразования fract к fract16 или long fract к fract32, где это необходимо. Например:

Подробнее см. описание bitsfx во врезке ниже.

Набор функций семейства bitsfx предоставляет побитное преобразование типа с фиксированной точкой в целое число.

Указанный операнд в формате с фиксированной точкой функция преобразует в значение, умноженное на 2 F , где F это количество бит дробной части типа с фиксированной точкой. Это эквивалентно передачи поля бит значения с фиксированной точкой в значение, которое хранится в целочисленном типе.

[Пример]

См. также fxbits.

Подобным образом, чтобы преобразовать поле бит в тип с фиксированной точкой, используйте семейство функций fxbits. Так например, чтобы преобразовать из fract32 в long fract, используйте:

Подробнее см. описание fxbits во врезке ниже.

Набор функций семейства fxbits предоставляет побитное преобразование целого числа в тип числа с фиксированной точкой.

Указанный целочисленный операнд будет преобразован в целое число, поделенное на 2 F , где F это количество бит, отведенное под дробную часть числа с фиксированной точкой. Это эквивалентно передаче значений поля бит целого числа, которое хранит тип числа с фиксированной точкой.

[Условия возникновения ошибки]

Семейство функций fxbits никогда не возвратит информацию о возникновении ошибки. Если входное целое число не помещается в количество бит результата с фиксированной точкой, то тогда результат получит насыщение к самому большому или самому малому числу в соответствующем представлении с фиксированной точкой.

[Пример]

См. также bitsfx.

[Арифметические операторы для типов с фиксированной точкой]

Вы можете использовать операторы +, -, * и / для типов с фиксированной точкой, и эти операторы будут иметь тот же эффект, как и их эквиваленты для целых чисел, кроме любой семантики переполнения или округления. Как уже обсуждалось выше, операции с фиксированной точкой, которые приводят к переполнению, получат насыщение к самому большому или самому малому представимому типом fixed-point значению. Округление обсуждается в разделе «Поведение округления».

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

Любые из этих операций могут быть использованы совместно с присваиванием, например:

Кроме того, есть некоторое количество унарных операторов, которые можно использовать с типами фиксированной точки. Вот они:

++ эквивалентно добавлению целого числа 1.
— эквивалентно вычитанию целого числа 1.
+ унарный плюс, эквивалентно добавлению 0.0 (операция не оказывает эффекта).
— унарный минус, означает вычитанию значения из 0.0.
! 1, если значение равно 0.0, иначе 0.

[FX_CONTRACT]

В примере скалярного умножения (см. «Мотивирующий пример» выше) содержится операция накопления:

где переменная sum была типа accum, и значения из массивов a[i], b[i] были типа fract. Учитывая ранее рассмотренные правила, какой будет результат умножения? Поскольку оба числа a[i] и b[i] типа fract, то результат умножения будет тоже типа fract — другими словами, два операнда s1.15 при умножении друг на друга дадут результат s1.15. Таким образом, правила говорят, что это должно быть эквивалентно следующему коду:

Однако это означает следующее:

• Результат умножения должен быть округлен до s1.15; будут потеряны 15 бит точности.
• Результат умножения -1.0r на -1.0r должен быть FRACT_MAX, т. е. точно не 1.0.

С этим возникают две проблемы:

• Возможно, что Вы не хотели бы округлять дополнительные биты точности прежде, чем добавить результат умножения к sum. Выполнение преждевременного округления снизит точность накопления. Кроме того, процессор Blackfin имеет эффективную, одноцикловую инструкцию умножения с накоплением (multiply-accumulate, MAC), но она не отбрасывает дополнительные биты точности в результате умножения перед накоплением.
• На процессорах Blackfin инструкция MAC не делает насыщение -1.0r * -1.0r перед добавлением к регистру аккумулятора. И это снова дает эффект повышения точности в результате накопления, но не соответствует семантике типа с фиксированной точкой для примера скалярного умножения.

Чтобы сгенерировать эффективный код без потери точности, Вы должны в действительности написать:

Причина в том, что преобразование в более высокую точность типа accum перед умножением означает, что генерируемый код может удержать промежуточный результат умножения в формате s9.31, что означает отсутствие требований к насыщению результата или округления бит младшего порядка. Это также будет означать использование компилятором аппаратной инструкции MAC.

Для удобства, компилятор может сделать это за Вас, если будете использовать режим, известный как FX_CONTRACT. Имя FX_CONTRACT используется потому, что поведение подобно FP_CONTRACT в C99. Когда режим FX_CONTRACT включен, компилятор может удерживать промежуточные результаты в точности выше, чем это задает Technical Report. Другими словами, можно выбрать не округлять дополнительные биты точности или выполнять насыщение в промежуточном результате, если это нежелательно. Если выразиться точнее, компилятор удерживает промежуточный результат в повышенной точности при следующих обстоятельствах:

• Сохранение промежуточного результата с повышенной точностью будет более эффективным для нижележащего аппаратного обеспечения.
• Промежуточный результат не сохраняется обратно в любую именованную переменную.
• Нет явного преобразования типа для промежуточного результата.

приведет к использованию инструкции MAC. Но для этих двух примеров:

будет происходить приведение результата умножения обратно к типу fract перед применением накопления.

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

• Неявное преобразование типа unsigned fixed-point в больший по размеру signed fixed-point тип не будет приводить к первоначальному преобразованию в типа signed fixed-point меньшего размера.
• Умножение signed fract и unsigned fract может создать дробное умножение смешанного типа, вместо того, чтобы сначала преобразовать unsigned fract в signed fract.

По умолчанию для компилятора разрешено поведение FX_CONTRACT. Режимом FX_CONTRACT можно управлять прагмой (см. описание #pragma FX_CONTRACT в [1]), или с опций помощью командной строки (см. описание опций -fx-contract и –no-fx-contract [3]). Прагма может использоваться в области действия файла исходного кода или внутри функции. Здесь применяются те же правила области действия, что и для прагмы FX_ROUNDING_MODE [1].

[Поведение округления]

Что произойдет, когда long fract будет преобразовано в fract? 16 младших значащих бит не могут быть представлены в результате, поэтому при преобразовании они должны быть отброшены. В случае, когда значение long fract не может быть точно представлено значением типа fract, есть 2 выбора: результат может быть представлен ближайшим fract значением, которое больше исходного значения long fract, либо ближайшим значением, которое меньше чем исходное значение long fract. Это известно под термином поведение округления (rounding behavior).

На некоторые операции с фиксированной точкой также может влиять округление. Например, умножение двух дробных значений для генерации дробного результата того же размера требует отбрасывания определенного количества младших бит от полного результата. Например, умножение s1.15 * s1.15 даст полный результат s2.30. Это приведет к насыщению до s1.30 и 15 младших значащих бит должны быть отброшены, чтобы дать результат s1.15.

По умолчанию любые биты должны быть отброшены усечением. Например:

Это эквивалентно всегда округлению вниз до отрицательной бесконечности. Такая тенденция будет приводить к результатам, точность которых будет ухудшаться.

Если вычисления не дают требуемой точности, то Вы можете использовать смещенное (biased) или несмещенное округление к ближайшему значению. Компилятор поддерживает прагмы и опции командной строки для управления режимом округления. В режимах округления biased или unbiased результат будет округлен к ближайшему значению, которое можно представить типом результата, так что конечное значение будет 0x0080p-15r.

Разница между biased и unbiased округлением сказывается, когда значение для округления лежит точно на половине между двумя ближайшими значениями, которые может представить тип результата. В этом случае biased округление всегда округляет в сторону большего из этих двух значений, (с применением насыщения, если округление привело к переполнению), в то время как unbiased округление всегда округляет в сторону меньшего из значений, у которого младший значащий бит равен 0. Например:

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

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

• Преобразование значения с плавающей точкой в значение с фиксированной точкой приводит к округлению в сторону 0.
• Функции roundfx, strtofxfx и fxdivi всегда выполняют либо biased, либо unbiased округление, в зависимости от текущего состояния бита RND_MOD. Они не поддерживают режим округления отбрасыванием.

Подробнее об установке режима округления рассказано в разделе ниже.

[Установка режима округления]

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

• Обрезка (truncation), это режим округления по умолчанию.
• Biased округление к ближайшему большему значению.
• Unbiased округление к ближайшему меньшему значению.

Чтобы установить режим округления, Вы можете использовать прагму или опции компилятора.

Следующие опции командной строки компилятора управляют поведением округления [3]:

Указанный опцией режим округления станет режимом по умолчанию для всего исходного компилируемого кода.

Вы также можете использовать прагмы для более гибкого управления округлением. Вот они:

Если одна из этих прагм применена на области действия файла, то её влияние будет распространено до конца юнита трансляции, или пока не встретится другая прагма на уровне файла, которая поменяет текущий режим округления.

Если одна из этих прагм была применена в пределах области действия составного оператора (т. е. блока кода, ограниченного фигурными скобками), то влияние прагмы будет распространяться до конца составного оператора. Режим округления будет возвращено к режиму, который действовал до входа в область действия составного оператора.

Пример того, как использовать прагмы для управления округлением, показан в листинге ниже.

У процессора Blackfin есть специализированные инструкции для поддержки округления к ближайшему значению. Однако, какое именно будет использоваться округление — biased или unbiased — зависит от текущего состояния бита RND_MOD. Чтобы упростить генерацию эффективного кода, компилятор предполагает, что когда режим округления либо biased, либо unbiased, бит RND_MOD был установлен в тот же тип округления. Это означает, что компилятор может эффективно использовать аппаратную поддержку для этих режимов округления без необходимости установки или очистки этого бита каждый раз при использовании инструкции, зависящей от бита RND_MOD.

Таким образом, в Вашей ответственности гарантировать, что бит RND_MOD установлен корректно. Для упрощения этой задачи предоставляются встроенные функции:

Эти функции возвращают предыдущее состояние бита RND_MOD. Имеется другая встроенная функция (void restore_rnd_mod(int)), которая сбрасывает бит RND_MOD в сохраненное состояние. Например, если Вы напишете:

Если Вы используете прагмы для указания режима округления без установки бита RND_MOD, то можете получить смесь biased и unbiased поведения округления. Для дополнительной информации см. «#pragma FX_ROUNDING_MODE » и «Changing the RND_MOD Bit» в руководстве [1].

[Арифметические библиотечные функции]

Заголовочный файл stdfix.h также декларирует некоторое количество функций, которые позволяют выполнять полезные арифметические операции на комбинациях типов чисел с фиксированной точкой и целых типов чисел. Это семейства функций divifx, idivfx, fxdivi, mulifx, absfx, roundfx, countlsfx и strtofxfx.

Функции divifx где fx заменяется на один из суффиксов r, lr, k, lk, ur, ulr, uk или ulk, позволяет выполнить деление целого числа на число с фиксированной точкой, чтобы получить в результате целое число.

Функция принимает целочисленное делимое numer и делитель denom в формате с фиксированной точкой, и функция вычислит частное и вернет ближайший целый результат.

У семейства функций divifx поведение не определено, когда делитель denom равен 0.

[Пример]

См. также fxdivi, idivfx.

[Почему следует использовать divifx]

Если Вы напишете:

то результат деления будет типа fract целая часть которого будет сохранена в переменной quo. Это означает, что значение quo будет 0, так как деление приведет к переполнению, и выдаст дробный результат, который близок к 1.

Чтобы получить желаемый результат, напишите:

В результате переменная quo получит значение 4.

Функции idivfx, где fx заменяется на один из суффиксов r, lr, k, lk, ur, ulr, uk или ulk, позволяет выполнять деление числа с фиксированной точкой на число с фиксированной точкой, чтобы получить целочисленный результат.

Принимая дробные значения делимого (numer) и делителя (denom), функция вернет целое значение, которое будет самым близким к результату деления.

У семейства функций idivfx поведение не определено, когда делитель denom равен 0.

[Пример]

См. также divifx, fxdivi.

[Почему следует использовать idivfx]

Если Вы напишете:


то результат деления будет fract, целая часть которого будет сохранена в переменной quo. Это означает, что значение quo будет 0, поскольку произойдет переполнение при делении, и это даст дробный результат, близкий к 1.

Чтобы получить желаемый результат, напишите:

тогда результат будет 2, и он будет записан в переменную quo.

Функции fxdivi, где fx заменяется на один из префиксов r, lr, k, lk, ur, ulr, uk или ulk, позволяют выполнить деление целого числа на целое, и в результате получить число с фиксированной точкой.

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

У семейства функций fxdivi поведение не определено, когда делитель denom равен 0.

[Пример]

См. также divifx, idivfx.

[Почему следует использовать fxdivi]

Если Вы напишете:

то результат деления будет целым числом, которое будет преобразовано во fract и присвоено переменной quo. Это означает, что значение переменной quo будет 0, потому что результат деления будет округлен к целому 0, и затем этот 0 будет преобразован в формат fract.

Чтобы получить желаемый результат, напишите:

полученное правильное значение 0.5 будет присвоено переменной quo.

Функции mulifx, где fx заменяется на один из суффиксов r, lr, k, lk, ur, ulr, uk или ulk, позволяют умножить целое число на число с фиксированной точкой, и получить в результате целое число.

Принимая целое число и число с в формате с фиксированной точкой, семейство функций mulifx вычисляет результат умножения и вернет ближайшее целое к полученному результату.

[Почему следует использовать mulifx]

Если Вы напишете:

то результат умножения будет fract, целая часть которого сохраняется в переменной prod. Это означает, что значение prod будет 0, так как умножение приведет к переполнению, и приведет к дробному числу, близкому к 1.

Чтобы получить правильный результат, напишите:

В этом варианте получится значение 25, которое будет присвоено переменной prod.

Функции absfx, где fx заменяется одним из суффиксов hr, r, lr, hk, k или lk, вычисляют абсолютное значение числа с плавающей точкой.

Дополнительно к индивидуально именованным функциям Вы также можете использовать универсальный по типу макрос absfx(), где тип операнда может быть любым знаковым (signed) типом с фиксированной точкой. Этот макрос предназначен для работы в режиме C99. Макрос возвратит тот же тип, что и его операнд.

[Пример]

См. также abs, fabs, labs.

Функции roundfx, где fx заменяется одним из суффиксов hr, r, lr, hk, k, lk, uhr, ur, ulr, uhk, uk или ulk, принимает 2 аргумента. Первый это операнд с фиксированной точкой, тип которого соответствует имени вызываемой функции. Второй параметр дает количество бит дробной части. Первый операнд округляется до указанного вторым параметром количества бит дробной части. Второй операнд должен задавать значение между 0 и количеством бит дробной части в округляемом типе. Округление происходит к ближайшему значению. Однако каким именно будет округление — смещенным (biased) или не смещенным (unbiased) — зависит от состояния бита RND_MOD аппаратуры. Подробнее см. раздел «Поведение округления». Если округленный результат выходит за пределы значений типа результата, то результат получит насыщение к максимуму или минимуму значения для типа результата с фиксированной точкой.

[Пример]

Дополнительно Вы также можете использовать универсальный по отношению к типу макрос roundfx(), где тип первого операнда может быть любым из типов с фиксированной точкой. Этот макрос определен для использования в режиме C99. Макрос вернет тот же тип, что и тип операнда.

Функции countlsfx, где fx заменяется одним из суффиксов hr, r, lr, hk, k, lk, uhr, ur, ulr, uhk, uk или ulk, возвратит самое большое значение k, которое соответствует операнду, сдвинутому влево на k настолько, что не произошло переполнение. Для нулевого входного операнда результат будет количеством бит в типе операнда.

Дополнительно также можно использовать макрос countlsfx(), где тип операнда может быть любым типом с фиксированной точкой. Этот макрос используется в режиме C99.

[Пример]

Функции strtofxfx, где fx заменяется одним из суффиксов hr, r, lr, hk, k, lk, uhr, ur, ulr, uhk, uk или ulk, анализируют строковое представление числа с фиксированной точкой и возвращают число в формате с фиксированной точкой. Функции ведут себя подобно функции strtod, и принимают входную строку в том же формате.

Подразумевается, что nptr указывает на строку, которая представляет число как десятичное с плавающей точкой или шестнадцатеричное с плавающей точкой. Любой из форм числа может предшествовать последовательность из символов пробела (как это определено функцией isspace), которая будет игнорироваться функцией.

Принимается следующая строка числа в представлении с десятичной плавающей точкой:

[sign] [digits] [.digits] [ [sign] [digits]]

Поле sign является необязательным, и может быть либо плюсом (+), либо минусом (–). Поле digits может быть одной или большим количеством символов десятичных цифр. Последовательность цифр может содержать десятичную точку (.).

За десятичными цифрами может идти экспонента, которая состоит из вводной буквы (e или E) и опционального целого знакового (signed) числа. Если не появляется ни десятичная точка, ни часть экспоненты, то предполагается, что десятичная точка следует за последней цифрой строки.

Принимается следующая строка числа в представлении с шестнадцатеричной плавающей точкой:

[sign] [<0x>|<0x>] [hexdigs] [.hexdigs] [ [sign] [digits]]

Строка шестнадцатеричного числа с плавающей точкой может начинаться с опционального плюса (+) или минуса (–), за которым идет префикс обозначения шестнадцатеричного числа 0x или 0X. За этой последовательностью символов должен идти один или большее количество шестнадцатеричных символов, последовательность которых может содержать десятичную точку (.).

За шестнадцатеричными символами идет двоичная экспонента, которая состоит из буквы p или P, опционального знака и не пустой последовательности десятичных цифр. Эта экспонента интерпретируется как степень двойки, которая используется для масштабирования дробного числа, представленного полями [hexdigs] [.hexdigs].

Первый символ в последовательности текста, который не удовлетворяет представленным формам числа, остановит сканирование строки. Если endptr не NULL, то по завершении работы функции он укажет на символ, который останавливает сканирование, и место, на котором было остановлено сканирование, будет сохранено в этом указателе.

[Условия возникновения ошибки]

Функции strtofxfx вернут 0, если не было произведено преобразование, и в объекте, на который указывает endptr, будет сохранен указатель на недопустимую строку. Если корректное значение результата привело к переполнению, то будет возвращено максимальное положительное или отрицательное число для заданного значения с фиксированной точкой. Если корректное значение привело к недогрузке (underflow, т. е. число слишком мало, чтобы его можно было представить заданным форматом с фиксированной точкой), то будет возвращен 0. В случае переполнения в errno будет сохранено значение ERANGE.

[Пример]

См. также strtod, strtol, strtoul.

[Спецификаторы формата преобразования ввода/вывода]

Семейство функций printf и scanf поддерживают спецификаторы преобразования для типов с фиксированной точкой. Они приведены в таблице 1-17. Обратите внимание, что спецификаторы преобразования для signed-типов, %r и %k, задаются в нижнем регистре, в то время как для unsigned-типов применяются %R и %K в верхнем регистре.

Таблица 1-17. Спецификаторы формата преобразования ввода/вывода для типов с фиксированной точкой.

Тип Спецификатор формата преобразования
short fract %hr
fract %r
long fract %lr
unsigned short fract %hR
unsigned fract %R
unsigned long fract %lR
short accum %hk
accum %k
long accum %lk
unsigned short accum %hK
unsigned accum %K
unsigned long accum %lK

При использовании с семейством функций scanf эти спецификаторы преобразования принимают тот же формат, который потребляют функции strtofxfx, который тот же самый какой применяется для %f. Для дополнительной информации см. врезку с описанием функций strtofxfx.

При использовании с семейством функций printf значения с фиксированной точкой печатаются следующим образом:

• По умолчанию как шестнадцатеричные значения, или когда используется опция командной строки компилятора -no-full-io. Например:

• Как значение с плавающей точкой, когда использовалась опция командной строки компилятора -fixed-point-io или -full-io. Например:

Принимаются опциональные спецификаторы точности, которые управляют количеством печатаемых десятичных цифр, и должна ли печататься завершающая десятичная точка. Однако они не дадут эффекта, за исключением использования опций командной строки -fixed-point-io или -full-io. Подробнее см. врезку с описанием функции fprintf.

Функция осуществляет форматированный вывод на печать в файловый поток.

Функция fprintf передает свой вывод печати в именованный выходной поток stream. Строка format (так называемая строка форматирования) задает, что будет выведено, и какие произойдут преобразования печатаемых аргументов.

Строка format содержать нулевое или большее количество спецификаторов формата преобразования, каждый из которых начинается символом процента (%). Сам спецификатор формата следует за символом %, и может содержать из одного или большего количества следующих полей:

• Flag – опциональные символы, которые модифицируют поведение преобразования параметра в текст.
• Width – опциональное числовое значение (или *), которое задает минимальную ширину поля.
• Precision – опциональное числовое значение, которое задает минимальное количество появляющихся цифр (задается точность преобразования).
• Length – опциональный модификатор, который указывает размер аргумента.
• Type – символ, который задает тип применяемого преобразования.

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

Флаг Поле
Левое выравнивание результата в пределах поля (по умолчанию результат выравнивается вправо).
+ Всегда начинает преобразование со знаком, где знак плюс или минус. По умолчанию только отрицательные значения указываются со знаком минус.
пробел Добавляется префикс из пробелов к результату, если если первый символ не знак минуса и также не был указан флаг +.
# Результат преобразуется в альтернативную форму в зависимости от типа преобразования:
o если значение не 0, то оно печатается с предшествием нулей.
x если значение не 0, то оно печатается с префиксом 0x.
X если значение не 0, то оно печатается с префиксом 0X.
a , A , e , E , f , F всегда генерирует появление десятичной точки.
0 (ноль) Задает альтернативу дополнению нулями. Начальные нули будут использоваться для необходимости дополнения поля до указаной ширины (спецификатором W >a , A , d , i , o , u , x или X . Флаг 0 может использоваться вместе с преобразованиями a , A , d , i , o , u , x , X , e , E , f , g и G .

Если задано поле width, то преобразованное значение дополняется пробелами до указанной ширины, если после преобразования количество символов оказалось меньше указанного значения. Обычно пробелы используются для дополнения поля слева, но будет использоваться дополнение справа, если указан флаг ‘-‘. Флаг ‘0’ может использоваться, чтобы заменить дополнение пробелами на дополнение символом 0 (см. описание флагов в таблице выше). Ширина width также может быть задана как ‘*’, что показывает, что текущий аргумент в вызове fprintf это число int, которое задает значение width. Если значение отрицательное, то оно интерпретируется как флаг ‘-‘ и положительное значение поля width.

Опциональное значение precision (точность) начинается с точки (.), за которой идет либо звездочка (*), либо десятичное целое число. Звездочка (*) показывает, что точность задана целочисленным аргументом, предшествующим форматируемуму выводимому аргументу. Если указана только точка, то подразумевается нулевая точность. Значение precision дает разные эффекты, в зависимости от используемого спецификатора преобразования:

• Для A точность указывает количество цифр после десятичной точки. Если точность нулевая, и не указан флаг #, то не будет сгенерирована десятичная точка.
• Для d, i, o, u, x, X задается минимальное количество появляющихся цифр, по умолчанию 1.
• Для f, F, E, e, k, K, r, R задается количество цифр после десятичной точки, по умолчанию 6. Если спецификатор # присутствует с нулевой точностью, то не будет сгенерирована десятичная точка.
• Для g, G задается максимальное количество значащих цифр.
• Для s, указывается максимальное количество записываемых символов.

Модификатор length может опционально использоваться для указания размерности аргумента. Модификаторы длины должны предшествовать только спецификаторам преобразования d, i, o, u, x, X, k, K, r, R или n, если не детализованы другие спецификаторы преобразования.

Length Действие
h Аргумент должен быть представлен типом short int, short fract или short accum.
hh Аргумент должен интерпретироваться как тип char.
j Аргумент должен быть представлен типом intmax_t или uintmax_t.
l Аргумент должен быть представлен типом long int, long fract или long accum.
ll Аргумент должен интерпретироваться как тип long long int.
L Аргумент должен интерпретироваться как long double. Этот модификатор длины должен предшествовать спецификаторам преобразования a, A, e, E, f, F, g или G.
t Аргумент должен интерпретироваться как ptrdiff_t.
z Аргумент должен интерпретироваться как size_t.

Обратите внимание, что спецификаторы размера hh, j, t и z, как это описано в стандарте C99 (ISO/IEC 9899:1999), доступны толкьо в случае выбора опции компилятора -full-io.

Следующая таблица содержит определения допустимых спецификаторов преобразования, которые задают один из применияемых типов преобразования:

Спецификатор Преобразование
a, A Число с плавающей точкой.
c Символ.
d, i Десятичное целое со знаком.
e, E Научная нотация (мантисса/экспонента).
f, F Десятичное число плавающей точкой.
g, G Преобразование работает как e, E или f, F.
k Знаковый тип accum.
K Тип accum без знака.
n Указатель на число со знаком, к которому число символов, записанное до сих пор, будет сохранено без другого вывода.
o Беззнаковое восьмеричное.
p Указатель на void.
r Дробное (fract) со знаком.
R Дробное (fract) без знака.
s Строка символов.
u Целое число без знака.
x, X Число без знака в шестнадцатеричной нотации.
% Позволяет вывести на печать символ % без интерпретации его как начала спецификатора преобразования.

Спецификатор преобразования a|A преобразует число с плавающей точкой стиля [-]0xh.hhhhp±d, где до точки стоит одна из шестнадцатеричных цифр. Спецификатор преобразования a|A всегда содержит минимум одну цифру для экспоненты.

Спецификатор преобразования e|E преобразует число с плавающей точкой стиля [-]d.ddde±dd. Экспонента всегда содержит как минимум две цифры. Случай, когда e педшествует экспоненте, соответствует спецификатору преобразования.

Спецификатор преобразования f|F конвертирует десятичную строку вида [-]d.ddd.

Спецификатор преобразования g|G конвертирует как спецификаторы e|E или f|F, в зависимости от преобразуемого значения. Если экспонента значения преобразована меньше чем -4, или больше или равна precision, то используются преобразования e|E, иначе f|F.

Все спецификаторы преобразования a, A, e, E, f, F, g и G, когда аргумент представляет бесконечность, выведут inf или INF в том же регистре, в каком был задан спецификатор. Для всех спецификаторов a, A, e, E, f, F, g и G аргумент, который представляет результат NaN, выводится как nan или NAN в том же регистре, в каком был задан спецификатор.

Спецификаторы преобразования k|K and r|R преобразуют значение с фиксированной точкой в десятичную нотацию [-]d.ddd, когда Ваше приложение собрано с опцией командной строки компилятора -full-io или -fixed-point-io. Иначе спецификаторы k|K и r|R будут преобразованивать значение с фиксированной точкой как шестнадцатеричное.

Функция fprintf возвращает количество напечатанных в поток символов.

[Условия возникновения ошибки]

Если функция fprintf завершилась неудачно, то она вернет отрицательное значение.

[Пример]

См. также printf, snprintf, vfprintf, vprintf, vsnprintf, vsprintf.

[Портирование кода, написанного с использованием fract16 и fract32]

Если у Вас есть код, использующий типы fract16 и fract32 вместе со встроенными функциями и вызовами библиотечных функций, то возможно Вы захотите переписать свой код для использования новых традиционных типов с фиксированной точкой (native fixed-point). В этом разделе содержится несколько советов, как это сделать проще всего.

Поскольку fract являются 16-разрядным типом, и long fract является 32-разрядным типом, то базовая стратегия состоит в замене использования переменных fract16 на fract и переменных fract32 на long fract.

Во-первых, код написанный с использованием fract16 и fract32 часто содержит константы. Если они написаны с использованием суффиксов r16 и r32, то Вы можете просто поменять суффикс для создания типа native fixed-point.

Если Ваш код содержит шестнадцатеричные константы, то удобно использовать синтаксис двоичной экспоненты для преобразования констант:

Множество встроенных функций (built-ins) больше не нужны, поскольку Вы перешли к использованию традиционных типов с фиксированной точкой – вместо этого можно использовать обычную арифметику. Соответствие между встроенными функциями для fract16 и fract32 и традиционными арифметическими действиями показано в таблице 1-18.

Таблица 1-18. Соответствие между встроенными функциями fract16 и строенными функциями fract32 и обычной арифметикой чисел с фиксированной точкой (Native Fixed-Point Arithmetic).

Встроенные функции fract16 или fract32 Традиционная арифметика с фиксированной точкой
fract16 f1, f2;
fract16 f3 = add_fr1x16(f1, f2);
fract f1, f2;
fract f3 = f1 + f2;
fract16 f1, f2;
fract16 f3 = sub_fr1x16(f1, f2);
fract f1, f2;
fract f3 = f1 — f2;
fract16 f1, f2;
fract16 f3 = mult_fr1x16(f1, f2);

fract f1, f2;
fract f3 = f1 * f2; // в режиме округления
// с отбрасыванием
fract16 f1, f2;
fract16 f3 = multr_fr1x16(f1, f2);

fract f1, f2;
fract f3 = f1 * f2; // в режиме округления
// biased/unbiased
fract16 f1, f2;
fract32 f3 = mult_fr1x32(f1, f2);
fract f1, f2;
long fract f3 = (long fract)f1 * (long fract)f2;
fract16 f1;
fract16 f2 = abs_fr1x16(f1);
fract f1;
fract f2 = absr(f1);
fract16 f1;
fract16 f2 = negate_fr1x16(f1);
fract f1;
fract f2 = -f1;
fract16 f1;
int n = norm_fr1x16(f1);
fract f1;
int n = countlsr(f1);
fract32 f1, f2;
fract32 f3 = add_fr1x32(f1, f2);
long fract f1, f2;
long fract f3 = f1 + f2;
fract32 f1, f2;
fract32 f3 = sub_fr1x32(f1, f2);
long fract f1, f2;
long fract f3 = f1 — f2;
fract32 f1;
fract32 f2 = negate_fr1x32(f1);
long fract f1;
long fract f2 = -f1;
fract32 f1;
int n = norm_fr1x32(f1);
long fract f1;
int n = countlslr(f1);
fract32 f1;
fract16 = trunc_fr1x32(f1);

long fract f1;
fract f2 = f1; // в режиме округления
// с отбрасыванием
#include
fract16 f1;
fract32 f2;
float f3;
f2 = fr16_to_fr32(f1);
f1 = fr32_to_fr16(f2);
f3 = fr16_to_float(f1);
f3 = fr32_to_float(f2);
f1 = float_to_fr16(f3);
f2 = float_to_fr32(f3);
fract f1;
long fract f2;
float f3;
f2 = f1;
f1 = f2;
f3 = f1;
f3 = f2;
f1 = f3;
f2 = f3;

Для удобства встроенные функции также предоставлены для того же функционала, что дают традиционные типы с фиксированной точкой, и нужно просто заменить в имени встроенной функции «fr» на «fx».

Например, если у Вас есть такой оригинальный код:

то Вы могли бы изменить его на следующий:

хотя чище было бы написать:

Имеется некоторое количество встроенных функций (built-ins), которые не могут напрямую отобразиться на арифметику с фиксированной точкой, но аналогичная функциональность все же доступна (подробнее см. таблицу 1-19). Эти встроенные функции выполняют дробное умножение 1.31 с округлением результата. Однако результат может не быть двоично идентичным результату, который был получен умножением традиционного long fract, даже в режиме округления к ближайшему значению, поскольку округление, выполняемое традиционными типами более точны, чем округление, предоставленное встроенными функциями. Рекомендуется использовать традиционную арифметику с фиксированной точкой, за исключением случаев, когда нужно побитно точно воспроизвести результаты Вашей предыдущей реализации. В таком случае Вы можете использовать побитно точный эквивалент встроенным функциям: mult_fx1x32x32, mult_fx1x32x32NS и multr_fx1x32x32.

Таблица 1-19. Встроенные функции fract16 и fract32 и традиционная арифметика с фиксированной точкой, имеющие подобную семантику.

Встроенные функции fract16 или fract32 Традиционная арифметика с фиксированной точкой
fract32 f1, f2;
fract32 f3 = mult_fr1x32x32(f1, f2);

long fract f1, f2;
long fract f3 = f1* f2; // режим округления
// biased/unbiased
fract32 f1, f2;
fract32 f3 = multr_fr1x32x32(f1, f2);

long fract f1, f2;
long fract f3 = f1* f2; // режим округления
// biased/unbiased
fract32 f1, f2;
fract32 f3 = mult_fr1x32x32NS(f1, f2);
long fract f1, f2;
long fract f3 = f1* f2; // режим округления
// biased/unbiased

Имеется множество библиотечных функций, которые используют типы fract16 и fract32. Как общее правило, Вы можете просто заменить «fr» на «fx», чтобы получить библиотечную функцию, которая примет вместо типов fract16 и fract32 и/или вместо типов fract16 и fract32 возвратит традиционные типы с фиксированной точкой. Однако нет аналогичной версии с фиксированной точкой для типа вектора fract2x16 или для комплексных дробных типов complex_fract16 и complex_fract32, поэтому специальные усилия должны быть предприняты, когда используется смесь традиционных типов с фиксированной точкой и векторных или комплексных дробных типов. Типы fract2x16, complex_fract16 и complex_fract32 могут быть использованы с традиционными типами, пока правильно осуществляется доступ к данным членов класса в функциях конструктора и аксессора, приведенных в таблице 1-20.

Таблица 1-20. Функции Constructor и Accessor для использования с традиционными типами фиксированной точки (Native Fixed-Point) и с комплексными и векторными дробными типами (Complex and Vector Fractional).

Встроенная функция Описание
complex_fract16 ccompose_fx_fr16 (fract real,
fract imag);
Создает значение типа complex_fract16 из типов fract вещественной и дробной части.
fract real_fx_fr16 (complex_fract16 c); Распаковывает вещественную часть типа fract из комплексного значения типа complex_fract16.
fract imag_fx_fr16 (complex_fract16 c); Распаковывает мнимую часть типа fract из комплексного значения типа complex_fract16.
complex_fract32 ccompose_fx_fr32(long fract real,
long fract imag);
Создает значение complex_fract32 из типов long fract вещественной и реальной части комплексного числа.
long fract real_fx_fr32 (complex_fract32 c); Распаковывает вещественную часть числа типа long fract из комплексного значения типа complex_fract32.
long fract imag_fx_fr32 (complex_fract32 c); Распаковывает мнимую часть числа типа long fract из комплексного значения типа complex_fract32.
fract2x16 compose_fx_fr2x16 (fract x, fract y); Создает значение типа fract2x16 из двух величин типа fract.
fract low_of_fx_fr2x16 (fract2x16 vec); Распаковывает младшую часть типа fract из значения типа fract2x16.
fract high_of_fx_fx2x16 (fract2x16 vec); Распаковывает старшую часть типа fract из значения типа fract2x16.


Система именования библиотечных функций, которые берут смесь типов фиксированной точки и типов fract2x16, complex_fract16 или complex_fract32, добавляют префикс «fx_» перед «fr2x16», «fr16», или «fr32» в имени функции. Вы можете проверить имя, когда консультируетесь со страницей документации для библиотечной функции. Обратите внимание, что не требуется изменять имена функций, которые не используют типы fract16 или fract32.

В этой врезке рассматривается пример программы для вычисления вариантности массива 16-битных дробных чисел.

Вариантность (variance) массива значений samples[] вычисляется по формуле:

где n количество выборок в массиве.

Как это перекладывается на типы с фиксированной точкой? Выборки в массиве samples составляют дробные (fract) значения, так что для вычисления суммы всех значений выборок нужен тип с размерностью, который больше чем этот дробный тип. Если имеется меньше 256 выборок, то определенно сумма уложится в тип accum без появления насыщения. Тот же аргумент прикладывается к сумме квадратов выборок.

Однако выше приведенная формула также нуждается в вычислении промежуточного результата sample_length * sum(samples[i] * samples[i]). Умножение на sample_length означает, что не обязательно результат умножения уложится в диапазон типа accum.

Эквивалентная формула для вариантности будет следующая:

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

Сначала подключается заголовочный файл stdfix.h, чтобы можно было использовать обычный синтаксис fract и accum. Следующее, что Вы можете заметить, это явное использование #pragma FX_CONTRACT ON. Поскольку это поведение по умолчанию для режима FX_CONTRACT, то здесь не строго обязательно использовать такую прагму, но это полезно для того, чтобы четко представлять себе поведение кода в программе.

Функция вычисляет вариантность только если в массиве имеется больше одной выборки, иначе функция просто вернет 0.

Затем функция устанавливает режим округления. Здесь используется unbiased округление, чтобы достичь наибольшей точности результата. Это достигается совместным использованием прагмы FX_ROUNDING_MODE UNBIASED и встроенной функции set_rnd_mod_unbiased, как это обсуждалось ранее в разделе «Установка режима округления».

Цикл вычисляет сумму выборок и сумму квадратов. Поскольку режим FX_CONTRACT включен (ON), то точность не теряется, так как дробные числа перемножаются друг с другом и суммируются в типе accum.

После цикла сумма выборок делится на sample_length, чтобы получить среднее значение. Оно должно быть в диапазоне [-1.0,1.0). Значение сохраняется в переменную типа long fract, чтобы максимально сохранить точность.

Далее функция вычисляет разность между суммой квадратов и результатом среднего значения суммы выборок массива samples. Поскольку абсолютное значение среднего меньше или равно 1, то этот результат умещается в типе accum, и поскольку этот результат и сумма квадратов обе не отрицательные, то разность должна также уместиться в accum.

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

Arduino.ru

Преобразования типа чисел с фиксированной точкой.

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

Число с фиксированной точкой — почти такое же, как целое, но отмасштабированное на число кратное 2^n.
Например, для 32-разрядного числа формата 16.16 старшие 16 разрядов хранят целую часть, а младшие — дробную, например, значение «2.5» будет представлено как 0x00028000.
Хотелось бы иметь быстрые (!) преобразования 32-разрядных чисел форматов 16.16, 32.0, 24.8 друг в друга а также в 16-разрядные форматы 16.0 и 8.8, а также в 8-разрядный 8.0. Н у и не забыть про 24-разрядные числа, поддерживаемые AVR.
Форматы 32.0, 16.0 и 8.0 — обычные целые числа unsigned long, unsigned int и byte.

На Паскале что-то похожее (но очень неоптимальное) может выглядеть так:

а что-то похожее написать на С++ у меня не получилось (это фрагмент, строки 11, 13 и 16)

насколько я понял, класс требует соответствующего конструктора, в котором, опять же, потребуется доступа к отдельным байтам, т.е. как раз того, что хочется получить в результате. Ну и эффективность такого подхода внушает сомнения в оптимальности.
Хочется, чтобы в теле программы, например, преобразование 16.16->8.8 выглядело просто как чтение двух байт из серединки числа с перезаписью их в новое число. Т.е 4 ассемблерные инструкции.

Аналогичная диагностика полдучается и при

сейчас компилятор разворачивает такие конструкци как деление:

в идеале приведенные выше примеры должны выглядеть так:

C#: числовые типы (Numeric Types)

Тип SYSTEM псевдоним Суффикс Размер Диапазон
Целые числа со знаком (Signed integer)
sbyte SByte 8 bits –2 7 до 2 7 –1
short Int16 16 bits –2 15 до 2 15 –1
int Int32 32 bits –2 31 до 2 31 –1
long Int64 L 64 bits –2 63 до 2 63 –1
Целые числа бес знака (Unsigned integer)
byte Byte 8 bits 0 до 2 8 –1
ushort UInt16 16 bits 0 до 2 16 –1
uint UInt32 U 32 bits 0 до 2 32 –1
ulong UInt64 UL 64 bits 0 до 2 64 –1
Реальные числа (Real number)
float Single F 32 bits ± (

10 –45 до 10 38 ) double Double D 64 bits ± (

10 –324 до 10 308 ) decimal Decimal M 128 bits ± (

10 –28 до 10 28 )

Среди целочисленных (integral) типов int и long используются наиболее часто. Остальные применяются для функциональной совместимости или когда действительно необходимы большие числа. Из реальных чисел, float и double , также называемые числами с плавающей точкой (floatingpoint types), обычно используются для научных вычислений. Тип decimal обычно используется в финансовых вычислениях, где необходима десятичная арифметика и высокая точность. Различия между double и decimal приведены в следующей таблице:

double decimal
Внутреннее представление двоичное десятичное
Точность 15-16-значные цифровые данные 28-29-значные цифровые данные
Диапазон ±(

10 308 )

±(

10 28 )

Специальные значения +0, –0, +∞, –∞, NaN Нет
Скорость вычисления Зависит от процессора Не зависит от процессора и приблизительно в 10 раз медленнее чем double

В связи с тем что типы float и double в своем внутреннем представлении являются двоичными, литералы с дробной частью (десятичные) не являются совсем точными:

По этой причине float и double лучше не использовать для финансовых вычислений, для которых лучше подходит тип decimal , десятичный в своей основе и поэтому более точный для дробных десятичных чисел.

Числовые литералы (Numeric Literals)

Целочисленные литералы (Integral literals) могут использовать десятичную (decimal) или шестнадцатеричную (hexadecimal) запись; шестнадцатеричная обозначается префиксом 0x (например, 0x7f = 127). Реально-числовые литералы также используют десятичную и шестнадцатеричную запись (например, 1E06 ).

По умолчанию, компилятор определяет тип числовых литералов по следующим критериям: если литерал содержит десятичную точку или знак экспоненты ( E ) — это double , в противном случае — это int , uint , long , или ulong .

Тип литерала также можно указать с помощью суффиксов, перечисленных в таблице выше. Суффикс ставиться сразу после литерала, например:

Необходимость в суффиксах U и L возникает крайне редко, т.к. почти всегда типы uint , long , и ulong могут быть либо выведены либо неявно преобразованы из int :

Суффикс D технически излишен, т.к. все литералы с десятичной точкой приводятся к double . Суффиксы F и M более полезны: они необходимы при написании дробных литералов типа float или decimal . Без суффикса подобные литералы будут считаться типом double , который не преобразуется скрыто к float или decimal .

Преобразование чисел

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

Преобразование реальных чисел. Число типа float может быть скрыто преобразовано к double , поскольку double способно вместить все возможные значения float . Обратное преобразование должно быть явным. Преобразование между decimal и другими реальными типами должно быть явным.

Преобразование между реальными и целыми числами. Преобразование целых чисел в реальные может быть скрытым, а вот обратное должно быть явным. Преобразование реальных чисел в целые происходит путем отсечения дробной части (без округления). Если необходимо преобразование с округлением, нужно использовать System.Convert класс. Важно помнить, что преобразование больших целых чисел в числа с плавающей точкой сохраняет их величину (magnitude, колличество цифр), но может привести к потере точности (precision):

Числовые операторы

Арифметические операторы

Арифметические операторы: + — * / % . Они применимы ко всем числовым типам, корме 8- и 16-битных целочисленных типов.

При делении целых чисел остаток всегда отсекается. При делении на переменную равную нулю возникает ошибка времени исполнения, а при делении на литерал или константу 0 — ошибка времени компиляции.

Оператор % возвращает остаток после деления.

Инкремент и декремент

Операторы инкремента ++ (Incremantal) и декремента — (Decremental) увеличивают и уменьшают (соответственно) числа на 1. Они могут идти до или после переменной, в зависимости от того, когда необходимо изменить переменную: до или после вычисления выражения:

Переполнение и оператор check

При выполнении арифметических операций с целыми числами возможно переполнение (Integral overflow) — ситуация, когда полученный результат превышает арифметические пределы типы. Как правило оно происходит тихо: никакие исключения не выбрасываются.

Оператор checked заставляет генерировать ошибку при переполнении (OverflowException). Он воздействует на выражения с операторами ++, —, — (унарный, обозначающий отрицательное число), +, -, *, / и операторами явного приведения между целочисленными типами. Применять его можно либо к одному выражению, либо к блоку:

В последнем случае, если для какого-либо выражения или блока необходимо отключить проверку переполнения, аналогичным способом необходимо использовать оператор unchecked .

Побитовые (поразрядные, bitwise) операторы

Каждый целочисленный тип может быть представлен в виде последовательности бит:

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

К побитовым операторам относятся:

  • И — & — устанавливает (в значение 1) только те биты, которые установлены (имеют значение 1) в обоих операндах, остальные биты выключаются (устанавливаются в 0)
  • ИЛИ — | — устанавливает те биты которые установлены либо в одном, либо в другом операнде
  • ИСКЛЮЧАЮЩЕЕ ИЛИ — ^ — устанавливает только те биты, которые установлены либо в одном, либо в другом операнде, но не в обоих одновременно
  • ОТРИЦАНИЕ —

— унарный оператор: устанавливает те биты, которые не установлены в операнде

  • СДВИГ ВЛЕВО — — сдвигает биты левого операнда влево на число позиций, равное второму операнду
  • СДВИГ ВПРАВО — >> — сдвигает биты левого операнда вправо на число позиций, равное второму операнду
  • a ) ; // 11111010 == 250

    Для положительных чисел битовый сдвиг числа вправо на n равносилен целочисленному делению на 2 n . Битовый сдвиг влево на n бит равносилен (для положительных чисел) умножению на 2 n .

    Операции с 8-битные и 16-битные целыми числами

    8-битные и 16-битные целые числа ( byte , sbyte , short , ushort ) не имеют собственных операторов, поэтому C# неявно преобразовывает их в большие типы при необходимости. В связи с этим при компиляции может возникнуть ошибка, если результату попытаться снова назначить младший тип:

    В этом примере x и y скрыто преобразуются в int , чтоб над ними можно было выполнить сложение. Результат в связи с этим тоже будет иметь тип int , который не может быть скрыто преобразован обратно в short (т.к. это может привести к потере данных). Чтобы избежать ошибки, необходимо использовать явное приведение к типу:

    Операции над числами с плавающей точкой

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

    Деление ненулевого значения на ноль дает бесконечность:

    Деление ноль на ноль и вычитание бесконечности из бесконечности дает NaN :

    При использовании оператора сравнения == , значение NaN никогда не будет равно никакому другому значению, в том числе другому значению NaN . Для проверки значения на равенство NaN нужно использовать методы float.IsNaN и double.IsNaN :

    Однако, при использовании метода object.Equals два NaN значения будут равны:

    Преобразование чисел в строку, форматные строки

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

    Стандартные форматные строки для чисел

    Символ Значение Пример Результат Примечание
    G или g Общий (general) формат 1.2345, «G»
    0.00001, «G»
    0.00001, «g»
    1.2345, «G3»
    12345, «G3»
    1.2345
    1E-05
    1e-05
    1.23
    1.23E04
    Перключается на экспоненциальную запись для очень маленьких и больших чисел. Цифра ограничивает точность (количество цифр)
    F Формат с фиксированной точкой 2345.678, «F2»
    2345.6, «F2»
    2345.68
    2345.60
    Цифра указывает сколько знаков оставить после запятой
    N Формат с фиксированной точкой и разделителем групп 2345.678, «N2»
    2345.6, «N2»
    2,345.68
    2,345.60
    Тоже самое что и F, но с разделением групп (тысяч)
    Заполнение ведущими нулями 123, «D5»
    123, «D1»
    00123
    123
    Только для целых типов. Цифра указывает до какой длины дополнять, усечение не происходит
    56789, «E»
    56789, «e»
    56789, «E2»
    5.678900E+004
    5.678900e+004
    5.68E+004
    Цифра указывает точность (по умолчанию — 6)
    C Денежное значение 1.2, «C»
    1.2, «C4»
    $1.20
    $1.2000
    Цифра указывает количество знаков после запятой
    P Процент .503, «P»
    .503, «P0»
    50.30 %
    50 %
    Цифра указывает количество знаков после запятой
    Шестнадцатеричный формат 47, «X»
    47, «x»
    47, «X4»
    2F
    2f
    002F
    X — верхний регистр, x — нижний регистр
    R Округление 1f / 3f, «R» 0.333333343

    Указание иной форматной строки, пустой строки или null эквивалентно «G».

    Специальные форматные строки для чисел

    Символ Значение Пример Результат Примечание
    # Заполнитель для цифр 12.345, «.##»
    12.345, «.####»
    12.35
    12.345
    Заполнитель для нуля 12.345, «.00»
    12.345, «.0000»
    99, «000.00»
    12.35
    12.3500
    099.00
    . Десятичная точка
    Разделитель групп 1234, «#,###,###»
    1234, «0,000,000»
    1,234
    0,001,234
    Коэффициент 1000000, «#,»
    1000000, «#,,»
    1000
    1
    % Процентная запись 0.6, «00%» 60%
    E0, e0,
    E+0, e+0 E-0,
    e-0
    Экспоненциальная запись 1234, «0E0»
    1234, «0E+0»
    1234, «0.00E00»
    1234, «0.00e00»
    1E3
    1E+3
    1.23E03
    1.23e03
    Скобка для литерального символа 50, @»\#0″ #50 Используется в сочетании с префиксом @ в строках или можно применять //
    ‘xx»xx’ Скобка для литеральной строки 50, «0 ‘…’» 50 …
    ; Разделитель секций 15
    (5)
    zero
    другой символ Литерал 35.2, «$0 . 00c» $35 . 20c

    Преобразование строки в число, NumberStyles

    Преобразование строки в число можно осуществить с помощью статических методов Parse и TryParse . Подробно эти методы рассмотрены в разделе, посвященном форматированию и преобразованию строк.

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

    Комбинируемые члены NumberStyles :

    • AllowLeadingWhite — допускает наличие в начале входной строки пробелов
    • AllowTrailingWhite — допускает наличие в конце входной строки пробелов
    • AllowLeadingSign — допускает наличие в начале входной строки символов
    • AllowTrailingSign — допускает наличие в конце входной строки символов
    • AllowParentheses — допускает наличие во входной строке скобок
    • AllowDecimalPoint — допускает наличие во входной строке десятичной точки
    • AllowThousands — допускает наличие во входной строке разделителя разрядов
    • AllowExponent — допускает наличие во входной строке экспоненты
    • AllowCurrencySymbol — допускает наличие во входной строке символа валют
    • AllowHexSpecifier — допускает наличие во входной строке символа шестнадцатиричной записи

    Составные члены NumberStyles :

    • None — любые символы кроме цифр в входной строке не допустимы
    • Integer — допустимы символы для целых чисел
    • Float — допустимы символы для чисел с плавающей точкой
    • Number — допустимы символы для любых чисел
    • HexNumber — допустимы символы для шестнадцатиричной записи
    • Currency — допустимы символы для валюты
    • Any — допустимы любые символы

    Если входная строка содержит символы отличные от цифр, а NumberStyles не методу не передан, будет сгенерировано исключение.

    Илон Маск рекомендует:  Program - Ключевое слово Delphi
    Понравилась статья? Поделиться с друзьями:
    Кодинг, CSS и SQL