how to get fractional digits from decimal?

T

Thomas

Hello developers,

How to get fractional digits from decimal value without first converting to
string and searching for decimal character?
Example: 123.456 -> 456
Any ideas?

Thomas?
 
J

Jeroen Mostert

Thomas said:
How to get fractional digits from decimal value without first converting
to string and searching for decimal character?
Example: 123.456 -> 456
This is actually not a bad approach. Numerically, your question doesn't make
a lot of sense. To simply get the fractional part of a number (0.456) you
can use Math.Abs(x - Math.Truncate(x)), but in order to know that you need
to multiply that number by 1000, you have to know its (rounded) base 10
representation. What should the "fractional digits" be for the result of 1.0
/ 3.0? An infinite string of 3s? How about the result of 1.0 / 16.0? Is that
625 or "0625"?

The best approach depends on what you intend to use the result for. For
display, a string approach is fine. For calculation, it's dubious whether
you need this at all.
 
J

Jason L Lind

I think what you're looking for is returning a class that has the compound
properties. You can either write the class traditionally (which is useful if
you're going to send the results to another context)
ie:
public class MyData{public bool IsPublished{get;set;} public DateTime
UpdateAt{get;set;}}

and then
var articles = Articles.Select(a => new MyData(){ IsPublished =
a.IsPublished, UpdateAt = a.UpdateAt});

or use an anyomous class:
var articles = Articles.Select(a => new { IsPublished = a.IsPublished,
UpdateAt = a.UpdateAt});

If you're looking to itterate over the collection and update it I would
reccomend using a traditional foreach loop, although you may also consider
using List<T>.ForEach which you can use LINQ syntax on now.

Hope that helps,

Jason Lind
 
T

Thomas

Jeroen Mostert said:
This is actually not a bad approach. Numerically, your question doesn't
make a lot of sense. To simply get the fractional part of a number (0.456)
you can use Math.Abs(x - Math.Truncate(x)), but in order to know that you
need to multiply that number by 1000, you have to know its (rounded) base
10 representation. What should the "fractional digits" be for the result
of 1.0 / 3.0? An infinite string of 3s? How about the result of 1.0 /
16.0? Is that 625 or "0625"?

The best approach depends on what you intend to use the result for. For
display, a string approach is fine. For calculation, it's dubious whether
you need this at all.

Yes, I need this. Correct, numerically it makes no sense.

Thomas
 
T

Thomas

Peter Duniho said:
You first need to decide how many significant decimal digits you want to
keep. Even if you wanted to add the complexity of finding the
least-significant non-zero digit, not all numbers have one.

Once you've done that, it's simple to arithmetically determine the
fractional digits:

int digits = 3;
int scale = (int)Math.Pow(10, digits);
decimal num = 123.456m;
int fraction = (int)((num * scale) - ((int)num * scale));

Now, all that said: is there any particular reason you don't want to
convert to a string first? You are effectively doing a string-based
operation anyway, since the logic above relies on a specific textual
representation of the number. Though you don't say so explicitly, the
question itself carries an implication that the result may well be used in
the context of textual output. And a string-based solution would not be
susceptible to numerical issues such as round-off error and overflow.

I would think that the string-based solution would in fact be the most
practical approach.

Pete

The problem is that I need to keep all fractional digits, preferably as int/
I do not want to use string for performance reasons - need to optimize this
part as much as possible.
I am thinking of converting decimal to bits perfoming what I have to on this
level.

Thomas
 
G

Göran Andersson

Thomas said:
Yes, I need this. Correct, numerically it makes no sense.

Thomas

Why do you think that you need this?

Should the result from 1.2 be the same as from 1.00000000000000002?
 
A

Arne Vajhøj

Thomas said:
How to get fractional digits from decimal value without first converting
to string and searching for decimal character?
Example: 123.456 -> 456

The code below should show some of the possibilities.

Arne

====================================

using System;

namespace E
{
public class Program
{
public static void Test(decimal x)
{
decimal y = x % 1m;
int z = (int)(1000*y);
decimal tmp = y;
while (tmp != (int)tmp && tmp < int.MaxValue/10)
{
tmp *= 10;
}
int w = (int)tmp;
Console.WriteLine(x + " " + y + " " + z + " " + w);
}
public static void Test(double x)
{
double y = x % 1;
int z = (int)(1000*y);
Console.WriteLine(x + " " + y + " " + z);
}
public static void Main(string[] args)
{
Test(123.456m);
Test(1m/3);
Test(123.456);
Test(1.0/3);
Console.ReadKey();
}
}
}
 
F

Family Tree Mike

Thomas said:
Hello developers,

How to get fractional digits from decimal value without first converting
to string and searching for decimal character?
Example: 123.456 -> 456
Any ideas?

Thomas?


Here is yet another approach. I frankly like the numerator and denominator
passsed back, but if you want the digits, they come back as well. It is
likely less efficient than strings though...

List<int> Fraction (double x, out long numerator, out long denominator)
{
List<int> Digits = new List<int>();
long frac = (long)(x * 1.0e16);

numerator = frac;
denominator = (long) 1.0e16;

long copy = numerator;
while (copy > 0)
{
int digit = (int) (copy % 10);
Digits.Add(digit);
copy = copy / 10;
}

Digits.Reverse();
return Digits;
}
 
R

rajkiranpro

decimal f = 123.456M;
f = f - Convert.ToInt32(f);
f = f * 10;
while (Math.Abs(f) != Convert.ToInt32(f))
{
f = f * 10;
}
int ans = Convert.ToIn32(f);
 
T

Thomas

Peter Duniho said:
Without a better explanation than that, no one can provide better answers
than you've been given.

I think there's a good chance there's some better way to approach whatever
it is you're trying to solve. But it's not possible to say without
something more than the original stated goal.


How do you know that using a string would be a performance problem?


That sentence doesn't make any sense to me. The clause "performing what I
have to on this level" is particularly problematic, though even the first
part doesn't have any immediately apparent relevance to the question.

Pete

I think the problem is well defined: create a function returing fractiona
digits from decimal, preferably as int type.
Thomas
 
T

Thomas

decimal d = 123.456m;

// 4th word, bits 16 to 23 contain precision
int precision = (Decimal.GetBits(d)[3] & 0x00FF0000) >> 16;
int n = Decimal.ToInt32(Decimal.Multiply(Decimal.Subtract(d,
Decimal.Truncate(d)), (decimal)Math.Pow(10, precision)));

Thomas
 
J

Jeff Johnson

I think the problem is well defined: create a function returing fractiona
digits from decimal, preferably as int type.

The deal is, many people approach a problem and THINK they have come up with
the best solution but they don't know how to implement it. So they come to a
newsgroup and state the SOLUTION, not the problem, and ask for help.

We newsgroup regulars, however, realize that lots of times the solution that
the poster has come up with is often NOT the best solution, and so we always
want to know what the problem is. When they refuse to tell us the original
problem, we tend to shrug and say "Whatever, you're on your own then."
 
K

Ken Foskey

Hello developers,

How to get fractional digits from decimal value without first converting
to string and searching for decimal character? Example: 123.456 -> 456
Any ideas?

Decimal fract = value - (int) value;

Parts after decimal point in fract now.

Ken
 
T

Todd Carnes

----- Original Message -----
From: "Thomas" <[email protected]>
Newsgroups: microsoft.public.dotnet.languages.csharp
Sent: Wednesday, January 14, 2009 3:46 PM
Subject: how to get fractional digits from decimal?

Hello developers,

How to get fractional digits from decimal value without first converting
to string and searching for decimal character?
Example: 123.456 -> 456
Any ideas?

Thomas?

decimal number; //the number of interest

int digits; // number of digits after the decimal that you're interested in
keeping

int fraction = (int)((number-(int)number) * Math.Pow(10,digits));
 
C

CLGan

using System.Math;

decimal fract = value - math.floor(fract);

Safer code, int may face some rounding problems 2.9 perhaps may become
3.....

(Above code hasn't go for full testing)
 
A

Arne Vajhøj

CLGan said:
using System.Math;

decimal fract = value - math.floor(fract);

Safer code, int may face some rounding problems 2.9 perhaps may become
3.....

Cast to int will truncate not round.

Arne
 
F

Family Tree Mike

CLGan said:
using System.Math;

decimal fract = value - math.floor(fract);

Safer code, int may face some rounding problems 2.9 perhaps may become
3.....

(Above code hasn't go for full testing)


I think you meant decimal fract = value - Math.Floor(value);

Hint: When you do full testing, test with a negative value.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top