Mike Mc Dermott

Michael McDermott

95 Reputation

3 Badges

17 years, 281 days
Self Employed
Circuit Analysis Engineer
Kokomo, Indiana, United States

Social Networks and Content at Maplesoft.com

MaplePrimes Activity


These are Posts that have been published by Mike Mc Dermott

Here is a procedure I wrote to apply a greek prefix to a value so that the coefficient lies between 1 and 1000.

 

applyGreekPrefix := proc(x)
	description
		"Accepts a number, and if it has units, a Greek prefix is added so that the coefficient is between 1 and 1000",
		"Values without units or a unit of muliple units are returned as-is"
	;
	local prefixes, powers, value, unit, exponent, new_value, idx, prefix, strUnit, new_unit, i, SIx, returnval;
	
	if Units:-Split(x)[2] = 1 or numelems(indets(op(2, x), 'name')) > 1 then	
		# Value has no units or consists of multiple units
		returnval := x;
	else
		# Define the SI prefixes and their corresponding powers of 10
		prefixes := ["q", "r", "y", "z", "a", "f", "p", "n", "μ", "m", "", "k", "M", "G", "T", "P", "E", "Z", "Y", "R", "Q"];
		powers := [seq(i, i = -30 .. 30, 3)];
		
		# Convert to SI unit w/o prefix
		SIx := convert(x, 'system', 'SI');		
		# Separate the value and the unit
		value := evalf(op(1, SIx));
		unit := op(2, SIx);
		strUnit := convert(unit, string);  # Convert the unit to a string representation
		
		# Calculate the exponent of 10 for the value
		exponent := floor(log10(abs(value)));
		
		# Find the closest power of 10 that makes the coefficient between 1 and 1000
		idx := 0;
		for i from 1 to nops(powers) do
		   if exponent >= powers[i] then
		       idx := i;
		   end if;
		end do;
		
		# Adjust the value based on the selected prefix
		new_value := value / 10^powers[idx];
		prefix := prefixes[idx];
		# Construct the new unit using Units:-Unit if a prefix is needed
		if prefix = "" then
		   new_unit := unit; # No prefix needed, use the original unit
		else
		   new_unit := parse(StringTools:-Substitute(strUnit, "Units:-Unit(", cat("Units:-Unit(", prefix))); # Construct a new unit with the prefix
		end if;
		
		# Return the adjusted value with the new unit
		returnval := new_value * new_unit;
	end if;	
	return returnval;
end proc:
list_tests:=[0.0001*Unit('kV'), 10000*Unit('V'), 10*Unit('V'/'us'), 12334];
for test in list_tests do
	print (test, "becomes", applyGreekPrefix(test));
end do;

 

I'm an engineer and when showing results of calculations, some values will display as fractions, and I would prefer that instead floating numbers are displayed.  Also, there is kind of a quirk where if the multiplier of a unit is 1, the result displays as a unit only. I would prefer to see 1*A rather than A.

I wrote this simple proc to convert a value with or without attached unit to a floating point number if it is a fraction or if it has a unit and the coefficient is 1.

Let me know if there is a more elegant way to do this or you have any suggestions or questions.

   unrationalize := proc(x)
        local 
            returnval,
            localcoeff,
            localunit
        ;
        description
            "Converts a fractional number to float",
            "Units are supported"
        ;
        if type(x, fraction) or type(x, with_unit(fraction)) then 
            returnval := evalf(x)
        elif type(x, with_unit(1, 'localcoeff', 'localunit')) then
            returnval :=  evalf(localcoeff)*localunit
        else 
            returnval := x;
        end if;
        return returnval;
    end  proc;
# Testing the proc
list1 := [1/2, 1/2*Unit(('A')/('V')), 1, Unit('A')];
listDescription := ["Fraction", "Fraction with Unit", "Unity", "Unity with Unit"];
for i, myValue in list1 do
    [listDescription[i], "evalf:", evalf(myValue), "unrationalize:", unrationalize(myValue)];
end do;

Page 1 of 1