Why is this Swift code getting errors? - ios

I am presently working on a first Swift project, and making a newcomer's errors.
The class I am working on is meant to export three of its methods to global variables:
var getAngle:[AnyObject]!;
var getHours:[AnyObject]!
var getMinutes:[AnyObject]!;
class GpsViewController : UIViewController {
// ....
required init() {
// super.init();
formatter.dateFormat = "yyyy-MM-dd";
parser.locale = NSLocale(localeIdentifier: "en_US_POSIX");
parser.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZ";
getAngle = self.restrictToAngle;
getHours = self.restrictToHours;
getMinutes = self.restrictToMinutes;
}
func getHourAndAngle() { // Hour hand angle in radians from 12 o'clock position, clockwise.
var now = NSDate();
var today = now;
var todayFormatted = this.formatter(today);
var yesterday = today.dateWithTimeIntervalSinceNow(-24 * 60 * 60);
var yesterdayFormatted = this.formatter(yesterday);
var tomorrow = today.dateWithTimeIntervalSinceNow(24 * 60 * 60);
var tomorrowFormatted = this.formatter(tomorrow);
var yesterdaySunset = this.presentLocation[yesterdayFormatted]["sunset"];
var todaySunrise = this.presentLocation[todayFormatted]["sunrise"];
var todaySunset = this.presentLocation[todayFormatted]["sunset"];
var tomorrowSunrise = this.presentLocation[tomorrowFormatted]["sunrise"];
var duration = 0.0;
var position = 0.0;
var startingHour = 18;
var offset = 0.0;
if now.isLessThanDate(todaySunrise) {
length = todaySunrise.timeIntervalSinceDate(yesterdaySunset);
position = now.timeIntervalSinceDate(yesterdaySunset);
offset = -0.5;
} else if now.isLessThanDate(todaySunset) {
length = todaySunset.timeIntervalSinceDate(todaySunrise);
position = now.timeIntervalSinceDate(todaySunrise);
offset = 0.5;
startingHour = 6;
} else {
length = tomorrowSunrise.timeIntervalSinceDate(todaySunset);
position = now.timeIntervalSinceDate(todaySunset);
offset = 1.5;
}
var proportion = position / length;
var angle = M_PI + (2 * M_PI * (proportion + offset));
var hours = floor(24 * 60 * 60 * ((1 + proportion + offset) % 1.0) / (60 * 60));
var minutes = floor(24 * 60 * 60 * (1 + proportion + offset) % 60 * 60);
return ["angle": angle, "hour": hour, "minutes": minutes];
}
func restrictToHours() {
return getHoursMinutesAngle["hour"];
}
func restrictToAngle() {
return getHoursMinutesAngle["angle"];
}
func restrictToMinutes() {
return getHoursMinutesAngle["minutes"];
}
// ...
}
I'm getting several errors, including in init()'s assignment of getAngle, "Value of type GpsViewController has no member restrictToAngle".
Could you tell me what the n00b errors are here?

You are trying to assign a function self.restrictToAngle to getAngle, a variable of type [AnyObject]! (i.e. an array).

As #EricD and others pointed out, there are quite a lot of issues. For understanding how function definition, calls & return type work in swift, check this Apple documentation page.

Related

How to get decibels accurately with AVAudioRecorder?

After comparing more than 20 apps, I found that the decibel values measured by each app are different.
// Method 1:
float power = [self.audioRecorder averagePowerForChannel:0];
float powerMax = [self.audioRecorder peakPowerForChannel:0];
power = power + 160 - 50;
int dB = 0;
if (power < 0.f) {
dB = 0;
} else if (power < 40.f) {
dB = (int)(power * 0.875);
} else if (power < 100.f) {
dB = (int)(power - 15);
} else if (power < 110.f) {
dB = (int)(power * 2.5 - 165);
} else {
dB = 110;
}
NSLog(#"power = %f, powerMax = %f , dB = %d",power, powerMax,dB);
// Method 2:
float level; // The linear 0.0 .. 1.0 value we need.
float minDecibels = -80.0f; // Or use -60dB, which I measured in a silent room.
float decibels = [self.audioRecorder averagePowerForChannel:0];
if (decibels < minDecibels)
{
level = 0.0f;
}
else if (decibels >= 0.0f)
{
level = 1.0f;
}
else
{
float root = 2.0f;
float minAmp = powf(10.0f, 0.05f * minDecibels);
float inverseAmpRange = 1.0f / (1.0f - minAmp);
float amp = powf(10.0f, 0.05f * decibels);
float adjAmp = (amp - minAmp) * inverseAmpRange;
level = powf(adjAmp, 1.0f / root);
}
NSLog(#"leval %f", level * 120);
There is a big gap between Method 1 and Method 2
So,Are these methods accurate? Is there a more correct way?

How to generate very sharp color scale for below zero and above zero?

I'm encountering a big problem when using the number 0 (zero) as a factor for the colors to generate scales, the numbers close to 0 (zero) end up becoming almost white, impossible to see a difference.
The idea is that above 0 (zero) it starts green and gets even stronger and below 0 (zero) starting with a red one and getting stronger.
I really need any number, even if it's 0.000001 already has a visible green and the -0.000001 has a visible red.
Link to SpreadSheet:
https://docs.google.com/spreadsheets/d/1uN5rDEeR10m3EFw29vM_nVXGMqhLcNilYrFOQfcC97s/edit?usp=sharing
Note to help with image translation and visualization:
Número = Number
Nenhum = None
Valor Máx. = Max Value
Valor Min. = Min Value
Current Result / Expected Result
After reading your new comments I understand that these are the requisites:
The values above zero should be green (with increased intensity the further beyond zero).
The values below zero should be red (with increased intensity the further beyond zero).
Values near zero should be coloured (not almost white).
Given those requisites, I developed an Apps Script project that would be useful in your scenario. This is the full project:
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu("Extra").addItem("Generate gradient", "parseData").addToUi();
}
function parseData() {
var darkestGreen = "#009000";
var lighestGreen = "#B8F4B8";
var darkestRed = "#893F45";
var lighestRed = "#FEBFC4";
var range = SpreadsheetApp.getActiveRange();
var data = range.getValues();
var biggestPositive = Math.max.apply(null, data);
var biggestNegative = Math.min.apply(null, data);
var greenPalette = colourPalette(darkestGreen, lighestGreen, biggestPositive);
var redPalette = colourPalette(darkestRed, lighestRed, Math.abs(
biggestNegative) + 1);
var fullPalette = [];
for (var i = 0; i < data.length; i++) {
if (data[i] > 0) {
var cellColour = [];
cellColour[0] = greenPalette[data[i] - 1];
fullPalette.push(cellColour);
} else if (data[i] < 0) {
var cellColour = [];
cellColour[0] = redPalette[Math.abs(data[i]) - 1];
fullPalette.push(cellColour);
} else if (data[i] == 0) {
var cellColour = [];
cellColour[0] = null;
fullPalette.push(cellColour);
}
}
range.setBackgrounds(fullPalette);
}
function colourPalette(darkestColour, lightestColour, colourSteps) {
var firstColour = hexToRGB(darkestColour);
var lastColour = hexToRGB(lightestColour);
var blending = 0.0;
var gradientColours = [];
for (i = 0; i < colourSteps; i++) {
var colour = [];
blending += (1.0 / colourSteps);
colour[0] = firstColour[0] * blending + (1 - blending) * lastColour[0];
colour[1] = firstColour[1] * blending + (1 - blending) * lastColour[1];
colour[2] = firstColour[2] * blending + (1 - blending) * lastColour[2];
gradientColours.push(rgbToHex(colour));
}
return gradientColours;
}
function hexToRGB(hex) {
var colour = [];
colour[0] = parseInt((removeNumeralSymbol(hex)).substring(0, 2), 16);
colour[1] = parseInt((removeNumeralSymbol(hex)).substring(2, 4), 16);
colour[2] = parseInt((removeNumeralSymbol(hex)).substring(4, 6), 16);
return colour;
}
function removeNumeralSymbol(hex) {
return (hex.charAt(0) == '#') ? hex.substring(1, 7) : hex
}
function rgbToHex(rgb) {
return "#" + hex(rgb[0]) + hex(rgb[1]) + hex(rgb[2]);
}
function hex(c) {
var pool = "0123456789abcdef";
var integer = parseInt(c);
if (integer == 0 || isNaN(c)) {
return "00";
}
integer = Math.round(Math.min(Math.max(0, integer), 255));
return pool.charAt((integer - integer % 16) / 16) + pool.charAt(integer % 16);
}
First of all the script will use the Ui class to show a customised menu called Extra. That menu calls the main function parseData, that reads the whole selection data with getValues. That function holds the darkest/lightest green/red colours. I used some colours for my example, but I advise you to edit them as you wish. Based on those colours, the function colourPalette will use graphical linear interpolation between the two colours (lightest and darkest). That interpolation will return an array with colours from darkest to lightest, with as many in-betweens as the maximum integer in the column. Please notice how the function uses many minimal functions to run repetitive tasks (converting from hexadecimal to RGB, formatting, etc…). When the palette is ready, the main function will create an array with all the used colours (meaning that it will skip unused colours, to give sharp contrast between big and small numbers). Finally, it will apply the palette using the setBackgrounds method. Here you can see some sample results:
In that picture you can see one set of colours per column. Varying between random small and big numbers, numerical series and mixed small/big numbers. Please feel free to ask any doubt about this approach.
A very small improvement to acques-Guzel Heron
I made it skip all non numeric values, beforehand it just errored out.
I added an option in the menu to use a custom range.
Thank you very much acques-Guzel Heron
function onOpen() {
const ui = SpreadsheetApp.getUi();
ui.createMenu('Extra')
.addItem('Generate gradient', 'parseData')
.addItem('Custom Range', 'customRange')
.addToUi();
}
function parseData(customRange = null) {
const darkestGreen = '#009000';
const lighestGreen = '#B8F4B8';
const darkestRed = '#893F45';
const lighestRed = '#FEBFC4';
let range = SpreadsheetApp.getActiveRange();
if (customRange) {
range = SpreadsheetApp.getActiveSpreadsheet().getRange(customRange);
}
const data = range.getValues();
const biggestPositive = Math.max.apply(null, data.filter(a => !isNaN([a])));
const biggestNegative = Math.min.apply(null, data.filter(a => !isNaN([a])));
const greenPalette = colorPalette(darkestGreen, lighestGreen, biggestPositive);
const redPalette = colorPalette(darkestRed, lighestRed, Math.abs(biggestNegative) + 1);
const fullPalette = [];
for (const datum of data) {
if (datum > 0) {
fullPalette.push([greenPalette[datum - 1]]);
} else if (datum < 0) {
fullPalette.push([redPalette[Math.abs(datum) - 1]]);
} else if (datum == 0 || isNaN(datum)) {
fullPalette.push(['#ffffff']);
}
}
range.setBackgrounds(fullPalette);
}
function customRange() {
const ui = SpreadsheetApp.getUi();
result = ui.prompt("Please enter a range");
parseData(result.getResponseText());
}
function colorPalette(darkestColor, lightestColor, colorSteps) {
const firstColor = hexToRGB(darkestColor);
const lastColor = hexToRGB(lightestColor);
let blending = 0;
const gradientColors = [];
for (i = 0; i < colorSteps; i++) {
const color = [];
blending += (1 / colorSteps);
color[0] = firstColor[0] * blending + (1 - blending) * lastColor[0];
color[1] = firstColor[1] * blending + (1 - blending) * lastColor[1];
color[2] = firstColor[2] * blending + (1 - blending) * lastColor[2];
gradientColors.push(rgbToHex(color));
}
return gradientColors;
}
function hexToRGB(hex) {
const color = [];
color[0] = Number.parseInt((removeNumeralSymbol(hex)).slice(0, 2), 16);
color[1] = Number.parseInt((removeNumeralSymbol(hex)).slice(2, 4), 16);
color[2] = Number.parseInt((removeNumeralSymbol(hex)).slice(4, 6), 16);
return color;
}
function removeNumeralSymbol(hex) {
return (hex.charAt(0) == '#') ? hex.slice(1, 7) : hex;
}
function rgbToHex(rgb) {
return '#' + hex(rgb[0]) + hex(rgb[1]) + hex(rgb[2]);
}
function hex(c) {
const pool = '0123456789abcdef';
let integer = Number.parseInt(c, 10);
if (integer === 0 || isNaN(c)) {
return '00';
}
integer = Math.round(Math.min(Math.max(0, integer), 255));
return pool.charAt((integer - integer % 16) / 16) + pool.charAt(integer % 16);
}

Convert Lat Long to X Y having lat/lon of corners of a map image

I've map image (1816 x 8160) having following lat/lon of corners.
TopLeft: (-73.9308,40.8883)
TopRight: (-73.8584,40.858)
BottomLeft: (-74.0665,40.7024)
BottomRight: (-73.9944,40.6718)
Map is not true north and rotated at 28.34, also its UTM Zone 18N (78W to 72W). Here are further details about this map taken from PDF Maps iOS app.
Size (pixels): 1816 x 6160
Pixel Resolution: 3.829 meters
Bounds (pixels): (-1624, -3518) x (7866, 7719)
PROJCS["WGS 84 / UTM zone 18N",
GEOGCS["WGS 84",
DATUM["WGS_1984",
SPHEROID["WGS 84",6378137,298.257223563,
AUTHORITY["EPSG","7030"]],
TOWGS84[0,0,0,0,0,0,0],
AUTHORITY["EPSG","6326"]],
PRIMEM["Greenwich",0,
AUTHORITY["EPSG","8901"]],
UNIT["degree",0.0174532925199433,
AUTHORITY["EPSG","9122"]],
AUTHORITY["EPSG","4326"]],
PROJECTION["Transverse_Mercator"],
PARAMETER["latitude_of_origin",0],
PARAMETER["central_meridian",-75],
PARAMETER["scale_factor",0.9996],
PARAMETER["false_easting",500000],
PARAMETER["false_northing",0],
UNIT["metre",1,
AUTHORITY["EPSG","9001"]],
AXIS["Easting",EAST],
AXIS["Northing",NORTH],
AUTHORITY["EPSG","32618"]]
How to convert lat/lon to x y and vice versa?
Any help will be much appreciated.
Thanks in advance.
var dot_size = 15;
var longitude_shift = 0; //-28.34; // number of pixels your map's prime meridian is off-center.
var x_pos = 0; //54;
var y_pos = 0; //19;
var map_width = 1380; //1816; //430;
var map_height = 4682; //6160; //332;
var half_dot = Math.floor(dot_size / 2);
// Converts from degrees to radians.
Math.radians = function(degrees) {
return degrees * Math.PI / 180;
};
// Converts from radians to degrees.
Math.degrees = function(radians) {
return radians * 180 / Math.PI;
};
/* N 40.88839 -73.93071 //-73.9308
E 40.85789 -73.85843 //40.858 -73.8584
W 40.70228 -74.06652 //40.7024 -74.0665
S 40.67185 -73.99437 //40.6718 -73.9944 */
var bottomX = 40.67185;
var bottomY = -73.99437;
var topX = 40.88839; //-73.9308; //-73.9308,40.8883
var topY = -73.93071;
var degreesPerPixelX = (bottomX - topX) / map_width; //0.07225 / map_width;
var degreesPerPixelY = (bottomY - topY) / map_height; //0.18605/ map_height;
// These should roughly box Germany - use the actual values appropriate to your image
var minLat = bottomX;
var minLong = bottomY;
var maxLat = topX;
var maxLong = topY;
// Map image size (in points)
var mapSize = {'width': map_width, 'height': map_height};
// Determine the map scale (points per degree)
var xScale = mapSize.width / (maxLong - minLong);
var yScale = mapSize.height / (maxLat - minLat);
var south = Math.radians(40.67185); //lat 47.2
var north = Math.radians(40.88839); //lat 55.2
var west = Math.radians(-74.06652); //long 5.8
var east = Math.radians(-73.85843); //long 15.2
// Formula for mercator projection y coordinate:
function mercY(lat) { return Math.log(Math.tan(lat/2 + Math.PI/4)); }
// Some constants to relate chosen area to screen coordinates
var ymin = mercY(south);
var ymax = mercY(north);
var xFactor = mapSize.width/(east - west);
var yFactor = mapSize.height/(ymax - ymin);
var mapLonLeft = -74.06652; //9.8;
var mapLonRight = -73.85843; //10.2;
var mapLonDelta = mapLonRight - mapLonLeft;
mapLatBottom = 40.67185; //53.45;
mapLatBottomRadian = mapLatBottom * Math.PI / 180;
function convertGeoToPixel(lat, lon)
{
pX = (lon - mapLonLeft) * (mapSize.width / mapLonDelta);
lat1 = lat * Math.PI / 180;
worldMapWidth = ((mapSize.width / mapLonDelta) * 360) / (2 * Math.PI);
mapOffsetY = (worldMapWidth / 2 * Math.log((1 + Math.sin(mapLatBottomRadian)) / (1 - Math.sin(mapLatBottomRadian))));
pY = mapSize.height - ((worldMapWidth / 2 * Math.log((1 + Math.sin(lat1)) / (1 - Math.sin(lat1)))) - mapOffsetY);
return 'x:'+pX+', y:'+pY;
}
function convertPixelToGeo(tx, ty)
{
/* called worldMapWidth in Raphael's Code, but I think that's the radius since it's the map width or circumference divided by 2*PI */
var worldMapRadius = mapSize.width / mapLonDelta * 360/(2 * Math.PI);
var mapOffsetY = ( worldMapRadius / 2 * Math.log( (1 + Math.sin(mapLatBottomRadian) ) / (1 - Math.sin(mapLatBottomRadian)) ));
var equatorY = mapSize.height + mapOffsetY;
var a = (equatorY-ty)/worldMapRadius;
var lat = 180/Math.PI * (2 * Math.atan(Math.exp(a)) - Math.PI/2);
var long = mapLonLeft+tx/mapSize.width*mapLonDelta;
return 'lat:'+lat+', lng:'+long;
}
function draw_point(x, y) {
dot = '<div style="position:absolute;width:' + dot_size + 'px;height:' + dot_size + 'px;top:' + y + 'px;left:' + x + 'px;background:#00ff00"></div>';
document.body.innerHTML += dot;
}
function plot_point(lat, lng) {
spotLat = lat;
spotLong = lng;
// Mercator projection
// longitude: just scale and shift
x = (map_width * (180 + lng) / 360) % map_width + longitude_shift;
// latitude: using the Mercator projection
lat1 = lat * Math.PI / 180; // convert from degrees to radians
y = Math.log(Math.tan((lat1/2) + (Math.PI/4))); // do the Mercator projection (w/ equator of 2pi units)
y = (map_height / 2) - (map_width * y / (2 * Math.PI)) + y_pos; // fit it to our map
x -= x_pos;
y -= y_pos;
// position of map image for point
//var newXY = 'x:' (spotLong - minLong) * xScale + ', y:' + (spotLat - minLat) * yScale +'<br/>';
//var y = (spotLat - minLat) * yScale;
//alert('x: ' + kavraX(Math.radians(lat),Math.radians(lng)) + ', y: ' + kavraY(Math.radians(lat),Math.radians(lng)));
strText = 'kavra x:' + kavraX(Math.radians(lat),Math.radians(lng)) + ', y:' + kavraY(Math.radians(lat),Math.radians(lng)) + '<br/>';
strText += 'x:' + x + ', y:' + y + '<br/>';
strText += 'x:'+(spotLong - minLong) * xScale +', y:' + (spotLat - minLat) * yScale +'<br/>';
strText += 'x:'+((Math.radians(lng) - west)*xFactor)+' ,y:'+((ymax - mercY(Math.radians(lat)))*yFactor)+'<br/>';
strText += convertGeoToPixel(lat,lng)+'<br/>' ;
//floatingDiv = '<div style="position:fixed;top:10px;left:10px;">'+strText+'</div>';
//document.body.innerHTML += floatingDiv;
$('#leftDiv').html(strText);
draw_point(x - half_dot, y - half_dot);
}
function kavraX (latitude, longitude) // Kavra for Kavrayskiy
// formula from http://en.wikipedia.org/wiki/Kavrayskiy_VII_projection
{
return ((3 * longitude) / 2 * Math.PI)*Math.sqrt(Math.pow(Math.PI, 2)/3 - Math.pow(latitude, 2));
}
function kavraY (latitude, longitude)
{
return latitude*-1;
}
$(document).ready(function() {
//-73.949321, 40.796997
plot_point(40.764296, -73.973027);
$('img').click(function(e) {
var offset = $(this).offset();
var relativeX = (e.pageX - offset.left);
var relativeY = (e.pageY - offset.top);
var clickedLon = topX + relativeX * degreesPerPixelX;
var clickedLat = bottomY + relativeY * degreesPerPixelY;
alert(relativeX+':'+relativeY+' lat:'+clickedLat+", lon:"+clickedLon);
});
$('#parentDiv').mousemove(function(e) {
var offset = $('img').offset();
var relativeX = (e.pageX - offset.left);
var relativeY = (e.pageY - offset.top);
var clickedLat = topX + relativeX * degreesPerPixelX;
var clickedLon = topY + relativeY * degreesPerPixelY;
//alert(relativeX+':'+relativeY+' lat:'+clickedLat+", lon:"+clickedLon);
var strText = relativeX+':'+relativeY+' lat:'+clickedLat+", lon:"+clickedLon+'<br/>';
strText += 'lat:'+(relativeY / yScale + minLat)+', long:'+(relativeX / xScale + minLong)+'<br/>';
strText += convertPixelToGeo(relativeX,relativeY)+'<br/>';
//floatingDiv = '<div style="position:fixed;top:10px;right:10px;">'+strText+'</div>';
//document.body.innerHTML += floatingDiv;
$('#rightDiv').html(strText);
});
});
/*$(function() {
$("#test").click(function(e) {
var offset = $(this).offset();
var relativeX = (e.pageX - offset.left);
var relativeY = (e.pageY - offset.top);
alert(relativeX+':'+relativeY);
$(".position").val("afaf");
});
});*/
function onClick (evt) {
alert(evt.pageX +' '+ evt.pageY);
var x = getEventOffsetFromImageLeft(evt);
var y = getEventOffsetFromImageTop(evt);
var clickedLon = topX + x * degreesPerPixelX;
var clickedLat = bottomY + y * degreesPerPixelY;
}
</script>
</head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<head>
</head>
<!-- onload="plot_point(40.756, -73.986)" -->
<body >
<div id='parentDiv'>
<!-- image found at http://i.stack.imgur.com/BXgSw.jpg -->
<img src="http://i.stack.imgur.com/BXgSw.jpg" style="position:absolute;top:0px;left:0px" >
<div id="leftDiv" style="position:fixed;top:10px;left:10px;"></div>
<div id="rightDiv" style="position:fixed;top:10px;right:10px;"></div>
</div>
</body>
</html>

Functions Returning A String - Swift

I'm doing a fraction calculator and I'm trying to add 2 fractions when I put in my fractions it just adds my Whole numbers only and nothing else if my fraction is 2 3/4 + 2 3/5 it add the whole numbers and outputs 4
var firstStep = firstDenomInTextField! * firstWholeInTextField! / firstDenomInTextField!
var secondStep = firstStep + firstNumInTextField! / firstDenomInTextField!
var thirdStep = secondDenomInTextField! * secondWholeInTextField! / secondDenomInTextField!
var fourthStep = thirdStep + secondNumInTextField! / secondDenomInTextField!
var calculatedAnswer = (secondStep + fourthStep)
var numerator = Int(calculatedAnswer * 10 * 10)
println(numerator)
answerLabel.hidden = false
answerLabel.text = printSimplifiedFraction(Numerator: numerator)
printSimplifiedFraction Function
func printSimplifiedFraction(Numerator numerator: Int, Denominator denominator: Int = 100) -> String
{
var finalNumerator = numerator;
var finalDenominator = denominator;
var wholeNumbers:Int = numerator / denominator;
var remainder:Int = numerator % denominator;
//println("wholeNumbers = \(wholeNumbers), remainder = \(remainder)");
//println("\(denominator) % \(remainder) = \(denominator % remainder)");
if(remainder > 0)
{
// see if we can simply the fraction part as well
if(denominator % remainder == 0) // no remainder means remainder can be simplified further
{
finalDenominator = denominator / remainder;
finalNumerator = remainder / remainder;
}
else
{
finalNumerator = remainder;
finalDenominator = denominator;
}
}
if(wholeNumbers > 0 && remainder > 0)
{
// prints out whole number and fraction parts
return("Simplified fraction of \(numerator)/\(denominator) = \(wholeNumbers) \(finalNumerator)/\(finalDenominator)");
}
else if (wholeNumbers > 0 && remainder == 0)
{
// prints out whole number only
return("Simplified fraction of \(numerator)/\(denominator) = \(wholeNumbers)");
}
else
{
// prints out fraction part only
return("Simplified fraction of \(numerator)/\(denominator) = \(finalNumerator)/\(finalDenominator)");
}
}
My Question I want to make it so it does not just add the whole numbers but add the whole fraction.
If you need any clarifications or questions please comment them down below
If you are working with fractions, you should use Double instead of Int. Also when multiplying by 10 you should use 10.0 instead. Be careful you are mixing Int(Integers) with Double(fractions). Also when declaring vars as parameters if you omit it will be a constant by default, if you would like to change it you don't need a second var, just add var in front of it when declaring it there).
I think You should restart it from the beginning, Syntax is OK. Don't forget to convert from Int to Double when needed.
I think your math is somewhat of in the code your present. The following code calculates the fraction and returns a string with the result.
...
var wholeTotal = firstWholeInTextField! + secondWholeInTextField!
var numeratorTotal = (firstNumInTextField! * secondDenomInTextField!) + (secondNumInTextField! * firstDenomInTextField!)
let denominatorTotal = firstDenomInTextField! * secondDenomInTextField!
while numeratorTotal > denominatorTotal {
wholeTotal++
numeratorTotal -= denominatorTotal
}
let resultString = simplifiedFractionStringWith(wholeTotal, numerator: numeratorTotal, denominator: denominatorTotal)
answerLabel.text = ("The result is: " + resultString)
func simplifiedFractionStringWith(wholeNumber: Int, numerator: Int, denominator: Int) -> String {
if numerator > 0 {
return ("\(wholeNumber) \(numerator)/\(denominator)")
} else {
return ("\(wholeNumber)")
}
}
That being said I really believe the whole thing is much better solved creating a fraction-struct...
Like I mentioned in my other answer I think the whole thing would be much better solved by creating a struct for your fraction. As I (clearly) have no life, I've put together another example:
struct fraction {
var wholeNumber = 0
var numerator = 0
var denominator = 0
func asString()-> String {
if numerator > 0 {
return ("\(wholeNumber) \(numerator)/\(denominator)")
} else {
return ("\(wholeNumber)")
}
}
func combinedWith(aFraction: fraction) -> fraction {
var wholeTotal = wholeNumber + aFraction.wholeNumber
var numeratorTotal = (numerator * aFraction.denominator) + (aFraction.numerator * denominator)
let denominatorTotal = denominator * aFraction.denominator
while numeratorTotal > denominatorTotal {
wholeTotal++
numeratorTotal -= denominatorTotal
}
let combinedFraction = fraction(wholeNumber: wholeTotal, numerator: numeratorTotal, denominator: denominatorTotal)
return combinedFraction
}
}
Then the code to show the total of two fractions would look something like this (in your app):
let firstFraction = fraction(wholeNumber: firstWholeInTextField!, numerator: firstNumInTextField!, denominator: firstDenomInTextField!)
let secondFraction = fraction(wholeNumber: secondWholeInTextField!, numerator: secondNumInTextField!, denominator: secondDenomInTextField!)
let combinedFraction = firstFraction.combinedWith(secondFraction)
answerLabel.text = ("The result is: " + combinedFraction.asString())

Spherical Coordinates within a range / restriction

The function below returns points on a sphere with a given radius. I want to add restriction such that points cannot be plotted within 30 degrees of the poles of the sphere.
public static function randomPoint(radius:Number):Number3D
{
var inclination:Number = Math.random() * Math.PI*2;
var azimuth:Number = Math.random() * Math.PI*2;
var point:Number3D = new Number3D(
radius * Math.sin(inclination) * Math.cos(azimuth),
radius * Math.sin(inclination) * Math.sin(azimuth),
radius * Math.cos(inclination)
);
return point;
}
Thanks in advance!
Sounds like you can just restrict the inclination:
var inclination:Number = (Math.PI/6) + Math.random()*(2*Math.PI-2*Math.PI/6)
Feel free to resolve those constant values, just kept them in to show the working.
Here's what I have so far... this does what I want, restricted north and south poles. Any improvements welcome!
var point:Number3D = sphericalPoint(100, inclination, azimuth);
public static function sphericalPoint(r:Number, inc:Number, az:Number):Number3D
{
var point:Number3D = new Number3D(
r * Math.sin(inc) * Math.cos(az),
r * Math.sin(inc) * Math.sin(az),
r * Math.cos(inc)
);
//cheat and use a transform matrix
var obj:Object3D = new Object3D();
obj.rotationX = 90;
point.rotate(point, obj.transform);
return point;
}
//a number between 0 and 180
protected function get inclination():Number
{
//default
//_inclination = Math.random() * Math.PI;
//number between 60 and 120
_inclination = Math.random() * (Math.PI*5/6 - Math.PI/6) + Math.PI/6;
return _inclination;
}
//a number between 0 and 360
protected function get azimuth():Number
{
//revolve around the Y axis
_azimuth = Math.random() * Math.PI*2;
return _azimuth;
}

Resources