C
C#15mo ago
se5a

❔ if(e == 1){e += double.Epsilon;}

I'm messing around with orbits, not wanting to deal with parabolic trajectories, I'm forcing them to be hyperbolic. however the above still equates to 1. Why?
31 Replies
Yawnder
Yawnder15mo ago
$floatingpoint
MODiX
MODiX15mo ago
Use double for non-integer math where the most precise answer isn't necessary. Use decimal for non-integer math where precision is needed (e.g. money). Use floats when you don't need high precision and/or when you need a large amount of non-integers.
Yawnder
Yawnder15mo ago
What I mean by that is that [any float] == [a specific number] is not a good idea. You should do a "close enough comparison". For example, if (Math.Abs(e - 1) < 0.0001) or similar. @.se5a
se5a
se5aOP15mo ago
I think you missunderstand. I don't want e to = 1
Yawnder
Yawnder15mo ago
No, I don't think I do misunderstand. baby crying gtg nevermind, the wife took care of him @.se5a So, yes. Why do you think I misunderstood?
se5a
se5aOP15mo ago
because that's the classic answer for the reverse of my problem.
Yawnder
Yawnder15mo ago
What do you mean? In your question you're doing a hard comparison of e == 1, and I'm telling you how you should do just that.
se5a
se5aOP15mo ago
if(e==1){e += double.Epsolon;}
if(e==1){//this is *still* true}
if(e==1){e += double.Epsolon;}
if(e==1){//this is *still* true}
Yawnder
Yawnder15mo ago
(I talked about float, but the same is true for double)
se5a
se5aOP15mo ago
if e is 1 I want to add the smalest amount possible so it's not 1
Yawnder
Yawnder15mo ago
If you want precise operations, you shouldn't use double and floats. There is no guarantee that a + b > a with these types. (even for a b > 0)
se5a
se5aOP15mo ago
I want precise operations. I don't want a parabolic orbit. because thats a third set of keplerian funtions. I want a hyperbolic orbit, where eccentricity is the smallest amount possible larger than 1 if the case ever arises that eccentricity IS 1. now I gtg for a couple of min lol
Yawnder
Yawnder15mo ago
Then you should use decimals if you want precise operations.
se5a
se5aOP15mo ago
doubles are close enough. I just want to change eccentricity enough that I'm no longer dealing with parabola
Yawnder
Yawnder15mo ago
Double aren't precise enough for what you want. double.Epsilon is actually smaller than the precision of doubles itself.
Developful
Developful15mo ago
what's decimal I know the rest of the types but haven't heard of decimal
Yawnder
Yawnder15mo ago
What do you mean?
Developful
Developful15mo ago
use double use floats and then there's use decimal is that a type?? ive literally never heard of it
se5a
se5aOP15mo ago
higher precision, slower, lower upper and lower bounds iirc
Yawnder
Yawnder15mo ago
Yup
MODiX
MODiX15mo ago
Yawnder
REPL Result: Success
public static string ToStringFull(double value)
{
if (value == 0.0) return "0.0";
if (double.IsNaN(value)) return "NaN";
if (double.IsNegativeInfinity(value)) return "-Inf";
if (double.IsPositiveInfinity(value)) return "+Inf";

long bits = BitConverter.DoubleToInt64Bits(value);
BigInteger mantissa = (bits & 0xfffffffffffffL) | 0x10000000000000L;
int exp = (int)((bits >> 52) & 0x7ffL) - 1023;
string sign = (value < 0) ? "-" : "";

if (54 > exp)
{
double offset = (exp / 3.321928094887362358); //...or =Math.Log10(Math.Abs(value))
BigInteger temp = mantissa * BigInteger.Pow(10, 26 - (int)offset) >> (52 - exp);
string numberText = temp.ToString();
int digitsNeeded = (int)((numberText[0] - '5') / 10.0 - offset);
if (exp < 0)
return sign + "0." + new string('0', digitsNeeded) + numberText;
else
return sign + numberText.Insert(1 - digitsNeeded, ".");
}
return sign + (mantissa >> (52 - exp)).ToString();
}
Console.WriteLine(ToStringFull(1));
Console.WriteLine(ToStringFull(double.Epsilon));
Console.WriteLine(ToStringFull(1 + double.Epsilon));
public static string ToStringFull(double value)
{
if (value == 0.0) return "0.0";
if (double.IsNaN(value)) return "NaN";
if (double.IsNegativeInfinity(value)) return "-Inf";
if (double.IsPositiveInfinity(value)) return "+Inf";

long bits = BitConverter.DoubleToInt64Bits(value);
BigInteger mantissa = (bits & 0xfffffffffffffL) | 0x10000000000000L;
int exp = (int)((bits >> 52) & 0x7ffL) - 1023;
string sign = (value < 0) ? "-" : "";

if (54 > exp)
{
double offset = (exp / 3.321928094887362358); //...or =Math.Log10(Math.Abs(value))
BigInteger temp = mantissa * BigInteger.Pow(10, 26 - (int)offset) >> (52 - exp);
string numberText = temp.ToString();
int digitsNeeded = (int)((numberText[0] - '5') / 10.0 - offset);
if (exp < 0)
return sign + "0." + new string('0', digitsNeeded) + numberText;
else
return sign + numberText.Insert(1 - digitsNeeded, ".");
}
return sign + (mantissa >> (52 - exp)).ToString();
}
Console.WriteLine(ToStringFull(1));
Console.WriteLine(ToStringFull(double.Epsilon));
Console.WriteLine(ToStringFull(1 + double.Epsilon));
Console Output
1.00000000000000000000000000
0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011125369292536009385779392
1.00000000000000000000000000
1.00000000000000000000000000
0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011125369292536009385779392
1.00000000000000000000000000
Compile: 734.216ms | Execution: 109.140ms | React with ❌ to remove this embed.
Yawnder
Yawnder15mo ago
(and see how deep epsilon is) 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011125369292536009385779392 You could do something like + 0.000001, but it might be too big for your liking.
se5a
se5aOP15mo ago
I'm using double. I expected 1+double.epsilon would not equate to 1. which is why I used double.epsilon
Yawnder
Yawnder15mo ago
I understand why you would expect that, but we're saying why it's not the case You though that double.Epsilon was the smallest "registerable number", but it's not.
se5a
se5aOP15mo ago
you've said it's not. you've not really stated why it's not.
Yawnder
Yawnder15mo ago
?!? Yeah, but it's not "double registrable"
reflectronic
reflectronic15mo ago
everything that has been said in this thread is incorrect the distance between two adjacent floating-point values increases as the magnitude increases. double.Epsilon represents the smallest increment greater than 0. it does not represent the smallest increment greater than 1, which is more than 300 times larger
se5a
se5aOP15mo ago
I figured it was somethig along those lines. Though I'm still not 100% sure exactly why that is the case, without doing a bunch of research
reflectronic
reflectronic15mo ago
it's inherent in the way floating-point numbers are stored a double can only represent multiples of powers of two. of the 64 bits in a double, 1 specifies the sign, 11 specify a power to which 2 is raised, and 52 specify a fraction providing the significant digits. multiplying these parts together lets you find the actual value or, in other words, the value is equal to (-1)^sign * 2^(exponent) * fraction it then follows that an increment m to the fraction (fraction + m) increases the value of the double by 2^(exponent) * m. so, when the exponent is increased by 1, the same increment to the fraction will result in double the increment to the actual value
se5a
se5aOP15mo ago
Ah, yeah that makes sense. Thanks
Accord
Accord15mo ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.
Want results from more Discord servers?
Add your server