Skip to content

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

Open

Description

@Lisias

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.

Activity

  1. self-assigned this
    on Jan 26, 2023
  2. zer0Kerbal commented on Jan 26, 2023

    @zer0Kerbal

    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.

  3. Lisias commented on Feb 12, 2023

    @Lisias
    Author

    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

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions