0

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.

Qantas 94 Heavy
  • 15,750
  • 31
  • 68
  • 83
Himadri
  • 2,922
  • 5
  • 32
  • 56
  • possible duplicate of [Round a double to x significant figures after decimal point](http://stackoverflow.com/questions/374316/round-a-double-to-x-significant-figures-after-decimal-point) – Eli Bendersky May 14 '10 at 06:00
  • @Eli No, that question is about rounding, my question is about comparing two double numbers without rounding. – Himadri May 14 '10 at 06:03
  • What programming language? I doubt this can be answered properly without that piece of information. – Oded May 14 '10 at 06:03
  • I am using delphi, but you just show me condition, if you don't know in delphi. I will write it my self. – Himadri May 14 '10 at 06:05
  • if you only effort yourself a little and search SO - there are tons of questions about comparing floats in various ways, rounding, etc. – Eli Bendersky May 14 '10 at 06:07

6 Answers6

4

(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
  • 25,628
  • 5
  • 56
  • 89
2

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
  • 489,969
  • 99
  • 883
  • 1,009
  • That would not work for the OP. In this case, they should be considered the same while with truncate they cannot. – Francesca May 14 '10 at 06:16
  • @François - Um. Which of the options would not work for the OP, and why? – Oded May 14 '10 at 06:18
  • 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 May 14 '10 at 06:25
  • 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. – Francesca May 14 '10 at 06:45
  • @François - I am assuming that the truncation/comparison is happening with the required precision. – Oded May 14 '10 at 06:53
2

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
Francesca
  • 21,452
  • 4
  • 49
  • 90
  • Afaik that doesn't satisfy the no rounding argument? – Marco van de Voort May 14 '10 at 06:42
  • Good answer, but it will return true if both numbers are exactly same. I want true only if they differ from 4th decimal. – Himadri May 14 '10 at 06:46
  • @Himadri. Edited to avoid the case when they are considered the same. – Francesca May 14 '10 at 07:10
  • 1
    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. – Werner Lehmann May 14 '10 at 17:26
0

Something like the following C# code:

if (Math.Abs(Math.Round(number1, 4) - Math.Round(number2, 4)) < 0.00001)
{
    number2 = number1;
}
Joe
  • 122,218
  • 32
  • 205
  • 338
0

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
  • 13,334
  • 11
  • 80
  • 154
0

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
  • 4,104
  • 2
  • 29
  • 45
  • Well It should return false in the case of CheckEqualUpTo4Digits(0.94618976, 0.94620239); as it is having 4th digit different.. – Himadri May 17 '10 at 11:09