Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using BCD in Module Manager **EXPERIMENTAL** #19

Open
Lisias opened this issue Jan 26, 2023 · 2 comments
Open

Using BCD in Module Manager **EXPERIMENTAL** #19

Lisias opened this issue Jan 26, 2023 · 2 comments
Assignees
Labels
enhancement New feature or request

Comments

@Lisias
Copy link

Lisias commented Jan 26, 2023

A fellow Kerbonaut approached me in Forum with this suggestion for improvement:

I wrote pretty simple code that shouldn't be too hard to implement in MM to use decimal floats for calculation when it can be represented in decimal and use double for when it can't.

using System;
					
public class Program
{
	static bool DecEval(double num)
	{
		bool Pass = true;	
		
		double UpLimit = 7.9E+28;
		double DownLimit = 1E-12;
		if (num > UpLimit || num < UpLimit*-1 || (num < DownLimit && num > DownLimit*-1 && num != 0))
		{
			Pass = false;
		}
		
		return Pass;
	}
	static string Clean0(string str)
	{
		int WorkingIndex = str.Length-1;
		if (str.IndexOf('.') != -1)
		{
			while (true)
			{
				if (str[WorkingIndex] == '0')
				{
					str = str.Substring(0,WorkingIndex);
					WorkingIndex = str.Length-1;
				} else if(str[WorkingIndex] == '.') {
					str = str.Substring(0,WorkingIndex);
					break;
				} else {break;}
			}
		}
		
		return str;
	}
	public static void Main()
	{
		String NumString1 = "-7.75"; // strings to mimic how ModuleManager starts and saves these numbers
		String NumString2 = "7.65";
		double Num1 = Convert.ToDouble(NumString1);
		double Num2 = Convert.ToDouble(NumString2);
		double Num3 = 0;
		
		decimal DecNum1 = 0;
		decimal DecNum2 = 0;
		decimal DecNum3 = 0;

		if (DecEval(Num1) && DecEval(Num2) && DecEval(Num1+Num2))
		{
			// string scientific notation to decimal doesn't work, so we have to go through a double float.
			// The way C# works should prevent any inaccuracies stimming from it, though, as most numbers with 13 digits or less will have a unique value and convert from double properly.
			// If they don't, well... it won't be less accurate than only double mathematics.
			if (NumString1.ToUpper().IndexOf('E') == -1) 
			{
				DecNum1 = Convert.ToDecimal(NumString1);
			} else {
				DecNum1 = Convert.ToDecimal(Num1);
			}
			
			if (NumString2.ToUpper().IndexOf('E') == -1)
			{
				DecNum2 = Convert.ToDecimal(NumString2);
			} else {
				DecNum2 = Convert.ToDecimal(Num2);
			}
			DecNum3 = DecNum1 + DecNum2;
		} else {
			Num3 = Num1+Num2;
		}
		
		if (Num3 == 0)
		{
			Console.WriteLine("Returning decimal {0}", Clean0(Convert.ToString(DecNum3)));
		} else {
			Console.WriteLine("Returning double {0}", Convert.ToString(Num3));
		}
	}
}

Source: https://dotnetfiddle.net/e2MC24

It sounds logical, but I need to consider that besides being a good idea using Big Numbers instear of floats when possible, this would make MM/L to behave differentlu from Forum's, and I'm unsure if this is a good idea.

The feature is solid, however - it's how MM should be doing things since ever.

@Lisias Lisias self-assigned this Jan 26, 2023
@Lisias Lisias added the enhancement New feature or request label Jan 26, 2023
@zer0Kerbal
Copy link

the forum's MM is dead. Nothing has been done on it that I can see in _how long??? and probably nothing will with the probably pre-release of KSP2 in less than a month.

@Lisias
Copy link
Author

Lisias commented Feb 12, 2023

Fellow Kerbonaut updated his reference code.

using System;
using System.Globalization;

public class Program
{
	static bool DecEval(double num)
	{
		bool Pass = true;	
		double UpLimit = 7.9E+28;
		double DownLimit = 1E-12;
		if (num > UpLimit || num < UpLimit*-1 || (num < DownLimit && num > DownLimit*-1 && num != 0))
		{
			Pass = false;
		}
		return Pass;
	}
	static string Clean0(string str)
	{
		int WorkingIndex = str.Length-1;
		if (str.IndexOf('.') != -1)
		{
			while (true)
			{
				if (str[WorkingIndex] == '0')
				{
					str = str.Substring(0,WorkingIndex);
					WorkingIndex = str.Length-1;
				} else if(str[WorkingIndex] == '.') {
					str = str.Substring(0,WorkingIndex);
					break;
				} else {break;}
			}
		}
		return str;
	}
	static string SMath(string NumString1, string Operator, string NumString2)
	{
		double Num1 = Convert.ToDouble(NumString1);
		double Num2 = Convert.ToDouble(NumString2);
		double Num3 = 0;
		decimal DecNum1 = 0;
		decimal DecNum2 = 0;
		decimal DecNum3 = 0;
		bool FirstPass = false;
		if (DecEval(Num1) && DecEval(Num2))
		{
			FirstPass = true;
			// string scientific notation to decimal doesn't work, so we have to go through a double float.
			// The way C# works should prevent any inaccuracies stimming from it, though, as most numbers with 13 digits or less will have a unique value and convert from double properly.
			// If they don't, well... it won't be less accurate than only double mathematics.
			if (NumString1.ToUpper().IndexOf('E') == -1) 
			{
				DecNum1 = Convert.ToDecimal(NumString1);
			} else {
				DecNum1 = Convert.ToDecimal(Num1);
			}
			if (NumString2.ToUpper().IndexOf('E') == -1)
			{
				DecNum2 = Convert.ToDecimal(NumString2);
			} else {
				DecNum2 = Convert.ToDecimal(Num2);
			}
		}
		if (Operator == "+")
		{
			if (FirstPass && DecEval(Num1 + Num2))
			{
				DecNum3 = DecNum1 + DecNum2;
			} else {
				Num3 = Num1 + Num2;
			}	
		} else if (Operator == "-")
		{
			if (FirstPass && DecEval(Num1-Num2))
			{
				DecNum3 = DecNum1 - DecNum2;
			} else {
				Num3 = Num1 - Num2;
			}	
		} else if (Operator == "*")
		{
			if (FirstPass && DecEval(Num1 * Num2))
			{
				DecNum3 = DecNum1 * DecNum2;
			} else {
				Num3 = Num1 * Num2;
			}	
		} else if (Operator == "/")
		{
			if (FirstPass && DecEval(Num1 / Num2))
			{
				DecNum3 = DecNum1 / DecNum2;
			} else {
				Num3 = Num1 / Num2;
			}	
		}
		if (Num3 == 0)
		{
			return Clean0(DecNum3.ToString(CultureInfo.InvariantCulture));
		} else {
			return Num3.ToString(CultureInfo.InvariantCulture);
		}
	}
	public static void Main()
	{
		Console.WriteLine(SMath("-7.75", "+", "7.65"));
		Console.WriteLine(SMath("-7.75", "-", "7.65"));
		Console.WriteLine(SMath("-7.75", "*", "7.65"));
		Console.WriteLine(SMath("-7.75", "/", "7.65"));
	}
}

Again, this is not exactly the code that will be use, but it demonstrates the feature.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants