I have a list of values such as "12000","12345","123456" that need to be converted to currency ("120.00", "123.45", "1234.56"). The only way I know is to convert the value to a string, copy the first strlen()-2 characters to one string (dollars) and the remainging two digits to another string(cents) and then write them as the following:
printf("%s.%s", dollars, cents);
printf("$%.2f", value/100);
Don't use floats for storing or representing monetary amounts. Use longs (if you need more than 4 billion cent use llongs). Its usually a good idea to represent currency in its minimum usable unit, example use 10000 to represent 100Euro). Then the correct way to format these values (assuming 100 cent to the euro or dollar) is:
printf( "%d.%02d", value/100, value%100);
Hope that makes sense...
Calculations with currency values is a complex subject but you cant go far wrong is you always aim to have a rounded answer to the nearest currency unit (cent for example) and always make sure that rounding errors are calculated for (example, to divide 1 dollar three ways you should end up with 33+33+34 or 33+33+33+1).
to prefix values less than $1.00 with 0, use:
printf( "$%0.2f", value / 100.0 );
This will result in $0.25 if value = 25
Related
I have the following piece of code. I want to format numbers with string templates. One variable has 2 decimal places, the other 4 decimal places but they represent the same number 50000 (fifty thousand).
The first number is correctly formatted (German representation) 50.000,00, the other one however is formatted as 5 million 5.000.000,00!
DATA: lv_p2 TYPE p LENGTH 9 DECIMALS 2,
lv_p4 TYPE p LENGTH 14 DECIMALS 4.
START-OF-SELECTION.
lv_p2 = '50000'.
lv_p4 = lv_p2.
SET COUNTRY 'DE'.
"This is correctly formatted as 50.000,00
WRITE |{ lv_p2 NUMBER = ENVIRONMENT CURRENCY = 'EUR' }|.
"This is on the other hand interpreted as five million! 5.000.000,00
WRITE |{ lv_p4 NUMBER = ENVIRONMENT CURRENCY = 'EUR' }|.
Is this documented somewhere? What am I doing wrong here?
EDIT:
It looks like the problem is with the addition CURRENCY. If I don't use it, then the number is correctly formatted.
WRITE |{ lv_p4 NUMBER = ENVIRONMENT }|.
or WRITE |{ lv_p4 NUMBER = ENVIRONMENT DECIMALS = 2 }|.
Anyway looks like some kind of a bug.
I believe this behaviour is documented.
ABAP Documentation - WRITE, format_options - CURRENCY cur
When CURRENCY is added:
"For data objects of type p, the decimal places determined by the
definition of the data type are ignored completely. Independently of
the actual value and without rounding, decimal separators and
thousands separators are inserted between the digits in the places
determined by cur."
Shortly: if CURRENCY is added (by WRITE), the number of decimal places is determined by the currency (in this case EUR has 2 decimal places), so the value 50.000,0000 will be 5.000.000,00. Same length (9 digits) only the number of decimals will be different.
I have a number with two digits after the decimal point; I try to cast this number using CAST for example:
Select SUM(CAST((123345.56) as decimal(28, 2))) * 100 AS AMOUNT
I get the following result
12334556.00
but I want get only 12334556 without displaying two digits after the decimal point.
Thank you.
It is not clear what you really want to do, but
SELECT SUM(CAST((123345.56 * 100.0) AS DECIMAL(28,0))) AS AMOUNT
gives 12334556.
When you use a number in the format 1234.56 it is a decimal literal in SQL Server: see "decimal constants" in Constants (Transact-SQL).
Integer data type is whole numbers, so cast your calculated value as int.
Select SUM(CAST((123345.56 * 100) as int)) AS AMOUNT
I was trying to round some fields. When I have 59 days, I want to change it to 60.
The problem is that when I use this code, the 59 is changed to 30 because the round it is 1.
select round(1.9666,0)*30, round(59/30,0)*3'
The result of that query is 60 for the first field and 30 for the second one. The problem is that when I've tried:
select 59/30
The result is 1 and I need the entire answer that is 1.9666...
How can I make it?
Because the number you are dividing by is an INT (the data type of the left side is irrelevant), SQL Server will return an INT as the answer.
If you want a number with a decimal place as your result, you'll need to divide by one.
Don't cast to a FLOAT as the answer is probably not what you want (floats are generally not accurate and are 'approximations'):
SELECT 59 / CAST(30 AS FLOAT) -- = 1.96666666666667
CAST the right-hand side of the division to a DECIMAL:
SELECT 59 / CAST(30 AS DECIMAL(10, 2)) -- = 1.96666
SELECT cast(59 AS FLOAT) / cast(30 AS FLOAT)
Because the original figures are whole numbers, SQL presumes you want a whole number output.
To ensure you get one with the decimal places, you need to first change the data type from an integer int to a floating point float.
This is what the CAST command does.
EDIT: Commenter suggests you cast to DECIMAL instead. The principle is the same, but you need to supply more arguments. To cast to a decimal use something like:
cast(59 as DECIMAL(18, 3))
The first argument (the 18) is the total number of figures you want to permit in the decimal. The second argument (the 3) is the number you want after the decimal point.
The suggestion that it's more accurate is correct - as you'll see if you run the SELECT statements in this answer one after the other. But in this particular case, it only makes a tiny difference.
MSSSQL 2008.
I have 3 Ints, 1 BigInt, 1 Float, and 1 DateTime value.
I am trying to concatenate them all into a single Char value and not lose any precision, which should let me create a single unique long value.
What are would the total character width be if I could make all of the numbers Chars and then combine them? The DateTime should go to MMDDYYHHMMSS.
Thanks.
INTs can be up to 10 digits.
BIGINTs can be up to 19 digits.
Floats could be anything. They have 38 digits of precision, but could be an enormous number with limited precision (1.79E + 308). You don't want that as a string. If your application has knowledge of what the actual range of values the float could be, you could make an application decision for a specific number of digits.
What is the best datatype for holding percent values ranging from 0.00% to 100.00%?
Assuming two decimal places on your percentages, the data type you use depends on how you plan to store your percentages:
If you are going to store their fractional equivalent (e.g. 100.00% stored as 1.0000), I would store the data in a decimal(5,4) data type with a CHECK constraint that ensures that the values never exceed 1.0000 (assuming that is the cap) and never go below 0 (assuming that is the floor).
If you are going to store their face value (e.g. 100.00% is stored as 100.00), then you should use decimal(5,2) with an appropriate CHECK constraint.
Combined with a good column name, it makes it clear to other developers what the data is and how the data is stored in the column.
Hold as a decimal.
Add check constraints if you want to limit the range (e.g. between 0 to 100%; in some cases there may be valid reasons to go beyond 100% or potentially even into the negatives).
Treat value 1 as 100%, 0.5 as 50%, etc. This will allow any math operations to function as expected (i.e. as opposed to using value 100 as 100%).
Amend precision and scale as required (these are the two values in brackets columnName decimal(precision, scale). Precision says the total number of digits that can be held in the number, scale says how many of those are after the decimal place, so decimal(3,2) is a number which can be represented as #.##; decimal(5,3) would be ##.###.
decimal and numeric are essentially the same thing. However decimal is ANSI compliant, so always use that unless told otherwise (e.g. by your company's coding standards).
Example Scenarios
For your case (0.00% to 100.00%) you'd want decimal(5,4).
For the most common case (0% to 100%) you'd want decimal(3,2).
In both of the above, the check constraints would be the same
Example:
if object_id('Demo') is null
create table Demo
(
Id bigint not null identity(1,1) constraint pk_Demo primary key
, Name nvarchar(256) not null constraint uk_Demo unique
, SomePercentValue decimal(3,2) constraint chk_Demo_SomePercentValue check (SomePercentValue between 0 and 1)
, SomePrecisionPercentValue decimal(5,2) constraint chk_Demo_SomePrecisionPercentValue check (SomePrecisionPercentValue between 0 and 1)
)
Further Reading:
Decimal Scale & Precision: http://msdn.microsoft.com/en-us/library/aa258832%28SQL.80%29.aspx
0 to 1 vs 0 to 100: C#: Storing percentages, 50 or 0.50?
Decimal vs Numeric: Is there any difference between DECIMAL and NUMERIC in SQL Server?
I agree with Thomas and I would choose the DECIMAL(5,4) solution at least for WPF applications.
Have a look to the MSDN Numeric Format String to know why :
http://msdn.microsoft.com/en-us/library/dwhawy9k#PFormatString
The percent ("P") format specifier multiplies a number by 100 and converts it to a string that represents a percentage.
Then you would be able to use this in your XAML code:
DataFormatString="{}{0:P}"
If 2 decimal places is your level of precision, then a "smallint" would handle this in the smallest space (2-bytes). You store the percent multiplied by 100.
EDIT: The decimal type is probably a better match. Then you don't need to manually scale. It takes 5 bytes per value.
Use numeric(n,n) where n has enough resolution to round to 1.00. For instance:
declare #discount numeric(9,9)
, #quantity int
select #discount = 0.999999999
, #quantity = 10000
select convert(money, #discount * #quantity)