views:

274

answers:

6

I have two decimal numbers. I want those number to be same upto 4 decimal points without rounding. If numbers are different I want 2nd number to be replaced by 1st. What if condition should I write?

Eg,
1.

num1 = 0.94618976  
num2 = 0.94620239

If we round these numbers upto 4 decimal then we get 0.9462 same number, but I don't want to round these numbers.

2.

num1 = 0.94620239  
num2 = 0.94639125  

The one way I found is take absolute difference of both numbers say diff and then check the value. My problem is of checking the range of diff.

I am using delphi but you can answer in any language.Thank You.

+2  A: 

There are several possibilities - as you did not supply a language, I will outline the approach.

You can use a truncate function (this is different from rounding), that simply drops the digits that are the higher precision (so 0.94618976 becomes 0.9461 and 0.94620239 becomes 0.9462). You can compare the results of the truncation.

If your language of choice does not support direct numeric truncation, you can convert to a string representation and only compare the first N characters.

If you were working with integers I would suggest comparing bit patterns, but you are using floating point, so this is not really an option.

Oded
That would not work for the OP. In this case, they should be considered the same while with truncate they cannot.
François
@François - Um. Which of the options would not work for the OP, and why?
Oded
@Oded I don't want to truncate, but the idea of converting into string is good. I even can convert them into int by multiplying 10000.
Himadri
@Oded. My understanding is that 0.94618976 and 0.94620239 should be found "equal" while in both of your solutions, they would differ on the 4th decimal.
François
@François - I am assuming that the truncation/comparison is happening with the required precision.
Oded
A: 

Something like the following C# code:

if (Math.Abs(Math.Round(number1, 4) - Math.Round(number2, 4)) < 0.00001)
{
    number2 = number1;
}
Joe
Questioner doesn't want rounding
Simon Nickerson
@Joe In this case, It will be also matched if both values are same upto 4 decimal. I don't want rounding.
Himadri
+2  A: 

Use something like SameValue from the Math unit:

if SameValue(num1, num2, 0.000099999999999) and not SameValue(num1, num2) then 
  num2 := num1; // only when different and by less then 0.0001
François
Afaik that doesn't satisfy the no rounding argument?
Marco van de Voort
Good answer, but it will return true if both numbers are exactly same. I want true only if they differ from 4th decimal.
Himadri
@Himadri. Edited to avoid the case when they are considered the same.
François
Does not work. You can't reliably compare N digits just by looking at the difference of two numbers. To see why let EPS = 0.000099999999999, num1 = 0.5555 - eps/4, num2 = 0.5555 + eps/4. Then we have num2 - num1 < eps and SameValue would return true. However, first 4 digits are not equal and OP would like to see num1 and num2 as different.
deepc
+4  A: 

(assuming no negative numbers, and assuming delphi as per tag) use trunc().

trunc(num1*10000.0)=trunc(num2*10000.0)

the multiplication with 10000 makes it integer numbers, and then everything is easy.

If you calculate 10000.0 (e.g. with power(10,n) ), you can even make the number of digits runtime variable.

Marco van de Voort
@Marco You write just I write in comment of Oded's answer.
Himadri
I'm working, took some time to write it. It was parallel. It is the standard solution btw.
Marco van de Voort
A: 

Look in the Delph MATH unit. You will find the "RoundTo" and "SimpleRoundTo" routines.

type
 TRoundToEXRangeExtended = -20..20;

function RoundTo(const AValue: Extended;
                 const ADigit: TRoundToEXRangeExtended): Extended;

{ This variation of the RoundTo function follows the asymmetric arithmetic
  rounding algorithm (if Frac(X) < .5 then return X else return X + 1).  This
  function defaults to rounding to the hundredth's place (cents). }

function SimpleRoundTo(const AValue: Extended; const ADigit: TRoundToRange = -2): Extended;
Brian Frost
@Brian My question is about if condition for comparing two numbers not for rounding
Himadri
@Himadri: Sorry, I did not read your question correctly.
Brian Frost
A: 

Just a thought, but how about this :

function CheckEqualUpTo4Digits(const aValue1, aValue2: Double): Boolean;
var
  Diff: Double;
begin
  Diff := Abs(aValue1 - aValue2);
  Result := (Diff < 0.0001);
end;

With this code, this returns True :

CheckEqualUpTo4Digits(0.94618976, 0.94620239);

And this returns False :

CheckEqualUpTo4Digits(0.94620239 , 0.94639125)

I haven't tested this much, but you could give it a shot - at least it uses no rounding, no conversion to another type (like what could happen with truncation), and is reasonably fast.

PatrickvL
@PatrickvL Well It should return false in the case of CheckEqualUpTo4Digits(0.94618976, 0.94620239); as it is having 4th digit different..
Himadri