SASS: convert RGBa back to hex? - css
I am aware SCSS can convert Hex to RGBa, but is there an option for the opposite?
My situation is this: I am given a colour palette that I am not allow to change. This includes a solid accent colour:
$color-accent: #039B15;
I've been asked to use this as a pale background colour, with 80% opacity. That's easy, I can just use rgba():
$color-accent-bg: rgba($color-accent, .2);
However, there is a situation where I need to nest elements with the same opaque background colour - because the colours are opaque they darken when nested.
Is there a way I can convert $color-accent-bg back to hexidecimal with SASS?
Ps: tried using lighten() but that seems to only work up to 66% light.
IMO simple rgba($color-accent-bg, 1) would do the trick - it returns same color as $color-accent.
Otherwise, you can use #ie_hex_str($color). It converts colors to hex string in #AARRGGBB format.
Converts a color into the format understood by IE filters.
Examples: ...
ie-hex-str(rgba(0, 255, 0, 0.5)) => #8000FF00
Since it returns string, you can remove AA part like in last line in following snippet:
$color-accent: #039B15;
$color-accent-bg: rgba($color-accent, .2);
$ie-hex: ie_hex_str($color-accent-bg); //#33039B15
$back-to-color-accent: unquote('#' + str_slice($ie-hex, 4)); //#039B15
Convert RGBa to Hex(transparent. no background, 8-bit color).
Tested solution i have written this code in scss and then converted to sass
In your Scss put:
// convert string to number
#function to-number($value) {
#if type-of($value) == 'number' {
#return $value;
} #else if type-of($value) != 'string' {
#error 'Value for `to-number` should be a number or a string.';
}
$result: 0;
$digits: 0;
$minus: str-slice($value, 1, 1) == '-';
$numbers: ('0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9);
#for $i from if($minus, 2, 1) through str-length($value) {
$character: str-slice($value, $i, $i);
#if (index(map-keys($numbers), $character) or $character == '.') {
#if $character == '.' {
$digits: 1;
} #else if $digits == 0 {
$result: $result * 10 + map-get($numbers, $character);
} #else {
$digits: $digits * 10;
$result: $result + map-get($numbers, $character) / $digits;
}
}
}
#return if($minus, -$result, $result);;
}
#function decimal-round ($number, $digits: 0, $mode: round) {
$n: 1;
// $number must be a number
#if type-of($number) != number {
#warn '#{ $number } is not a number.';
#return $number;
}
// $digits must be a unitless number
#if type-of($digits) != number {
#warn '#{ $digits } is not a number.';
#return $number;
} #else if not unitless($digits) {
#warn '#{ $digits } has a unit.';
#return $number;
}
#if $digits > 0 {
#for $i from 1 through $digits {
$n: $n * 10;
}
}
#if $mode == round {
#return round($number * $n) / $n;
} #else if $mode == ceil {
#return ceil($number * $n) / $n;
} #else if $mode == floor {
#return floor($number * $n) / $n;
} #else {
#warn '#{ $mode } is undefined keyword.';
#return $number;
}
}
#function rgba-to-hex($rgba){
$colorCode: ( '0','1', '2','3','4','5','6','7','8','9','A','B','C','D','E', 'F');
// 255 / 100 = 2.55
// 10 / 16 = 0.625
$alpha: alpha($rgba);
// ============================================= RED ================================
$redStr: ''+(red($rgba) / 16);
$index: str-index($redStr, ".");
// add decimal number incase it does not have and update index
#if $index == null { $redStr: $redStr+'.0'; $index: str-index($redStr, ".");};
// #debug $redStr '========================================================';
$redInteger : to-number(str-slice($redStr, 0, $index - 1));
$redDecimal: decimal-round(to-number(str-slice($redStr, $index + 1, $index + 1)) / 0.625);
// ============================================= GREEN ============================
$greenStr: ''+(green($rgba) / 16);
$index: str-index($greenStr, ".");
// add decimal number incase it does not have and
#if $index == null { $greenStr: $greenStr+'.0'; $index: str-index($greenStr, ".");};
$greenInteger : to-number(str-slice($greenStr, 0, $index - 1));
$greenDecimal: decimal-round(to-number(str-slice($greenStr, $index + 1, $index + 1)) / 0.625);
// ============================================= BLUE ============================
$blueStr: ''+(blue($rgba) / 16);
$index: str-index($blueStr, ".");
// add decimal number incase it does not have and
#if $index == null { $blueStr: $blueStr+'.0'; $index: str-index($blueStr, ".");};
$blueInteger : to-number(str-slice($blueStr, 0, $index - 1));
$blueDecimal: decimal-round(to-number(str-slice($blueStr, $index + 1, $index + 1)) / 0.625) ;
// if interger is 16 sent decimal should be 0
//#debug 'blue: '+ $blueStr +' interter: '+ $blueInteger +' decimal: '+ $blueDecimal;
// $blue: blue($rgba) / 2.55;
// ============================================= ALPHA ============================
$alphaStr: ''+ decimal-round((($alpha*100)*2.55) /16) ;
$index: str-index($alphaStr, ".");
#if $index == null { $alphaStr: $alphaStr+'.0'; $index: str-index($alphaStr, ".");};
//#debug 'alphaStr: '+ decimal-round(to-number($alphaStr)) ;
$alphaInteger : ''+to-number(str-slice($alphaStr, 0, $index - 1));
$index: str-index($alphaInteger, ".");
#if $index == null { $alphaInteger: $alphaInteger+'.0'; $index: str-index($alphaInteger, ".");};
$alphaInteger : to-number(str-slice($alphaStr, 0, $index - 1));
$alphaDecimal: to-number(str-slice(''+to-number(str-slice($alphaStr, $index + 1, str-length($alphaStr))) / 0.625, 0, 2)) ;
// #debug 'Integer: ==== '+$alphaInteger;
// #debug 'Decimal: ==== '+$alphaDecimal;
#return unquote("#"+nth($colorCode, $redInteger + 1)+nth($colorCode, $redDecimal + 1)+nth($colorCode, $greenInteger + 1)+nth($colorCode, $greenDecimal + 1) +nth($colorCode, $blueInteger + 1)+nth($colorCode, $blueDecimal + 1)+nth($colorCode, $alphaInteger + 1)+nth($colorCode, $alphaDecimal + 1));
};
Usage
$result : rgba-to-hex( rgba(192, 84, 84, 0.582));
#debug $result;
.my-class{
background-color: rgba-to-hex( rgba(192, 84, 84, 0.582));
}
OutPut
Terminal:
#C0535390
css build file:
.my-class{
background-color: #C0535390;
}
In your sass file put:
#function to-number($value)
#if type-of($value) == 'number'
#return $value
#else if type-of($value) != 'string'
#error 'Value for `to-number` should be a number or a string.'
$result: 0
$digits: 0
$minus: str-slice($value, 1, 1) == '-'
$numbers: ('0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9)
#for $i from if($minus, 2, 1) through str-length($value)
$character: str-slice($value, $i, $i)
#if (index(map-keys($numbers), $character) or $character == '.')
#if $character == '.'
$digits: 1
#else if $digits == 0
$result: $result * 10 + map-get($numbers, $character)
#else
$digits: $digits * 10
$result: $result + map-get($numbers, $character) / $digits
#return if($minus, -$result, $result)
#function decimal-round ($number, $digits: 0, $mode: round)
$n: 1
#if type-of($number) != number
#warn '#{ $number } is not a number.'
#return $number
// $digits must be a unitless number
#if type-of($digits) != number
#warn '#{ $digits } is not a number.'
#return $number
#else if not unitless($digits)
#warn '#{ $digits } has a unit.'
#return $number
#if $digits > 0
#for $i from 1 through $digits
$n: $n * 10
#if $mode == round
#return round($number * $n) / $n
#else if $mode == ceil
#return ceil($number * $n) / $n
#else if $mode == floor
#return floor($number * $n) / $n
#else
#warn '#{ $mode } is undefined keyword.'
#return $number
#function rgba-to-hex($rgba)
$colorCode: ( '0','1', '2','3','4','5','6','7','8','9','A','B','C','D','E', 'F')
// 255 / 100 = 2.55
// 10 / 16 = 0.625
$alpha: alpha($rgba)
// ============================================= RED ================================
$redStr: ''+(red($rgba) / 16)
$index: str-index($redStr, ".")
// add decimal number incase it does not have and update index
#if $index == null
$redStr: $redStr+'.0'
$index: str-index($redStr, ".")
$redInteger : to-number(str-slice($redStr, 0, $index - 1))
$redDecimal: decimal-round(to-number(str-slice($redStr, $index + 1, $index + 1)) / 0.625)
// ============================================= GREEN ============================
$greenStr: ''+(green($rgba) / 16)
$index: str-index($greenStr, ".")
// add decimal number incase it does not have and
#if $index == null
$greenStr: $greenStr+'.0'
$index: str-index($greenStr, ".")
$greenInteger : to-number(str-slice($greenStr, 0, $index - 1))
$greenDecimal: decimal-round(to-number(str-slice($greenStr, $index + 1, $index + 1)) / 0.625)
// ============================================= BLUE ============================
$blueStr: ''+(blue($rgba) / 16)
$index: str-index($blueStr, ".")
#if $index == null
$blueStr: $blueStr+'.0'
$index: str-index($blueStr, ".")
$blueInteger : to-number(str-slice($blueStr, 0, $index - 1))
$blueDecimal: decimal-round(to-number(str-slice($blueStr, $index + 1, $index + 1)) / 0.625)
// ============================================= ALPHA ============================
$alphaStr: ''+ decimal-round((($alpha*100)*2.55) /16)
$index: str-index($alphaStr, ".")
#if $index == null
$alphaStr: $alphaStr+'.0'
$index: str-index($alphaStr, ".")
$alphaInteger : ''+to-number(str-slice($alphaStr, 0, $index - 1))
$index: str-index($alphaInteger, ".")
#if $index == null
$alphaInteger: $alphaInteger+'.0'
$index: str-index($alphaInteger, ".")
$alphaInteger : to-number(str-slice($alphaStr, 0, $index - 1))
$alphaDecimal: to-number(str-slice(''+to-number(str-slice($alphaStr, $index + 1, str-length($alphaStr))) / 0.625, 0, 2))
#return unquote("#"+nth($colorCode, $redInteger + 1)+nth($colorCode, $redDecimal + 1)+nth($colorCode, $greenInteger + 1)+nth($colorCode, $greenDecimal + 1) +nth($colorCode, $blueInteger + 1)+nth($colorCode, $blueDecimal + 1)+nth($colorCode, $alphaInteger + 1)+nth($colorCode, $alphaDecimal + 1))
$result : rgba-to-hex( rgba(192, 84, 84, 0.582))
#debug 'peter =='+$result
I didn't test the sass file i just remove the semicolon, '{' and '}'.
You could try #039B1580 but i believe this method doesn't work on all browsers
Related
Trouble when rendering voxels with pathtracing
I'm currently working on a pathtracer in c and open cl. I'm using this algorithm for rendering. The first collision works well, however, from the second collision onwards there is a dark shadow on the lower side of the voxels. This is the color of the voxel the initial ray hits: result This is the color of the voxel that the second ray hits: result And this is the result after rendering to a depth of 1000: result This is the code I used (openCL): int cast_ray(Renderer *r, Ray ray, float3 *hitPos, int3 *normal, Material *material) { int3 voxel = convert_int3(ray.origin); int3 step = { (ray.direction.x >= 0) ? 1 : -1, (ray.direction.y >= 0) ? 1 : -1, (ray.direction.z >= 0) ? 1 : -1 }; float3 tMax = { (ray.direction.x != 0) ? (voxel.x + step.x - ray.origin.x) / ray.direction.x : MAXFLOAT, (ray.direction.y != 0) ? (voxel.y + step.y - ray.origin.y) / ray.direction.y : MAXFLOAT, (ray.direction.z != 0) ? (voxel.z + step.z - ray.origin.z) / ray.direction.z : MAXFLOAT }; float3 tDelta = { (ray.direction.x != 0) ? 1 / ray.direction.x * step.x : MAXFLOAT, (ray.direction.y != 0) ? 1 / ray.direction.y * step.y : MAXFLOAT, (ray.direction.z != 0) ? 1 / ray.direction.z * step.z : MAXFLOAT }; int side; while(1) { if(tMax.x < tMax.y) { if(tMax.x < tMax.z) { voxel.x += step.x; tMax.x += tDelta.x; side = 0; } else { voxel.z += step.z; tMax.z += tDelta.z; side = 2; } } else { if(tMax.y < tMax.z) { voxel.y += step.y; tMax.y += tDelta.y; side = 1; } else { voxel.z += step.z; tMax.z += tDelta.z; side = 2; } } if(out_of_scene(r, voxel)) return 0; MaterialID id = get_material_ID(r, voxel); if(id == 0) continue; *material = get_material(r, id); switch(side) { case 0: hitPos->x = (float)voxel.x; hitPos->y = ray.origin.y + (hitPos->x - ray.origin.x) * ray.direction.y / ray.direction.x; hitPos->z = ray.origin.z + (hitPos->x - ray.origin.x) * ray.direction.z / ray.direction.x; *normal = (int3){-step.x, 0, 0}; break; case 1: hitPos->y = (float)voxel.y; hitPos->x = ray.origin.x + (hitPos->y - ray.origin.y) * ray.direction.x / ray.direction.y; hitPos->z = ray.origin.z + (hitPos->y - ray.origin.y) * ray.direction.z / ray.direction.y; *normal = (int3){0, -step.y, 0}; break; case 2: hitPos->z = (float)voxel.z; hitPos->y = ray.origin.y + (hitPos->z - ray.origin.z) * ray.direction.y / ray.direction.z; hitPos->x = ray.origin.x + (hitPos->z - ray.origin.z) * ray.direction.x / ray.direction.z; *normal = (int3){0, 0, -step.z}; break; } return 1; } } float3 get_color(Renderer *r, Ray ray) { float3 mask = 1; float3 color = 0; int maxDepth = 1000; for(int i = 0; i < maxDepth; i++) { float3 hitPos; int3 iNormal; Material material; if(cast_ray(r, ray, &hitPos, &iNormal, &material)) { float3 fNormal = convert_float3(iNormal); if(material.type == 1) { color = mask * material.color; break; } else if(material.type == 2) { float3 direction = fNormal + random_unit_vector(r->rng); ray = (Ray){hitPos, direction}; mask *= material.color; } else if(material.type == 3) { float3 direction = reflection_dir(ray.direction, fNormal) + random_unit_vector(r->rng) * material.fuzzyness; ray = (Ray){hitPos, direction}; mask = mask * (1 - material.tint) + mask * material.color * material.tint; } } else { color = mask * r->bgColor; break; } // if(i == 1) // return material.color; } return color; } I think that the problem is that the new origin of the ray is somehow not correct, but I can't find a way to fix it.
How to do the following SCSS in stylus
I have the following SASS function which i am struggling to convert to stylus. The online converters seem to struggle with it also. #function multiple-box-shadow ($n) $value: '#{random(2000)}px #{random(2000)}px white' #for $i from 2 through $n $value: '#{$value} , #{random(2000)}px #{random(2000)}px white' #return unquote($value)
The following works. random(min,max) return floor(math(0, 'random')*(max - min + 1) + min)px multiple-box-shadow($n) $value = random(0, 2000) random(0, 2000) white for $i in (1...$n) $value = $value , random(0, 2000) random(0, 2000) white return $value
Symfony Date to Hijri date conversion in twig file
In symfony template we can use the formatters like {{ news.created|date('Y-m-d') }} I need something similar for the hijri date conversion. Meaning I provide the date in gregorian and it convert it to hijri in the twig template file may be something like {{ news.created|hijridate }} I searched a lot on forums etc but did not find something relevant specifically in twig template.
After not finding any solution I make my own twig extension. I am pasting it hopefully it will help any one the input is the date object like {{ newsitem.created|hdate }} and ouput is الأربعاء 10 رمضان 1437 هـ Write a twig extension in src/AppBundle/Twig/HdateExtension.php with the following code. <?php namespace AppBundle\Twig; class HdateExtension extends \Twig_Extension { public function getFilters() { return array( new \Twig_SimpleFilter('hdate', array($this, 'hdateConvert') ) ); } public function hdateConvert($date) { if($date instanceof \DateTime){ $dateDay = $date->format('N'); $date->modify('+1 day'); $year = $date->format('Y'); $month = $date->format('m'); $day = $date->format('d'); } $dayH = array("الأثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت","الأحد"); // actual calculation $newDate = $dayH[$dateDay-1]." ".HdateExtension::Greg2Hijri($day, $month, $year, true ); return $newDate; } public function getName() { return 'hdate_extension'; } public function Greg2Hijri($day, $month, $year, $string = false) { $day = (int) $day; $month = (int) $month; $year = (int) $year; if (($year > 1582) or (($year == 1582) and ($month > 10)) or (($year == 1582) and ($month == 10) and ($day > 14))) { $jd = HdateExtension::intPart((1461*($year+4800+HdateExtension::intPart(($month-14)/12)))/4)+HdateExtension::intPart((367*($month-2-12*(HdateExtension::intPart(($month-14)/12))))/12)- HdateExtension::intPart( (3* (HdateExtension::intPart( ($year+4900+ HdateExtension::intPart( ($month-14)/12) )/100) ) ) /4)+$day-32075; } else { $jd = 367*$year-HdateExtension::intPart((7*($year+5001+HdateExtension::intPart(($month-9)/7)))/4)+HdateExtension::intPart((275*$month)/9)+$day+1729777; } $l = $jd-1948440+10632; $n = HdateExtension::intPart(($l-1)/10631); $l = $l-10631*$n+354; $j = (HdateExtension::intPart((10985-$l)/5316))*(HdateExtension::intPart((50*$l)/17719))+(HdateExtension::intPart($l/5670))*(HdateExtension::intPart((43*$l)/15238)); $l = $l-(HdateExtension::intPart((30-$j)/15))*(HdateExtension::intPart((17719*$j)/50))-(HdateExtension::intPart($j/16))*(HdateExtension::intPart((15238*$j)/43))+29; $month = HdateExtension::intPart((24*$l)/709); $day = $l-HdateExtension::intPart((709*$month)/24); $year = 30*$n+$j-30; $mname = array("محرّم","صفر","ربيع الأوّل"," ربيع الثاني","جمادى الأولى","جمادى الثانية","رجب","شعبان","رمضان","شوّال","ذو القعدة","ذو الحجّة"); $date = array(); $date['year'] = $year; $date['month'] = $mname[$month-1]; $month = $mname[$month-1]; $date['day'] = $day; if (!$string) return $date; else return "{$day} {$month} {$year} هـ "; } public function intPart($float) { if ($float < -0.0000001) return ceil($float - 0.0000001); else return floor($float + 0.0000001); } } Then add the following in the services.yml file app.twig_extension: class: AppBundle\Twig\HdateExtension public: false tags: - { name: twig.extension }
thanks for your code, symfony 5: <?php namespace App\Twig; use Exception; use Twig\Extension\AbstractExtension; use Twig\TwigFilter; class HdateExtension extends AbstractExtension { /** * #return TwigFilter[] */ public function getFilters(): array { return [ new TwigFilter( 'hdate', [ $this, 'hdateConvert' ]) ]; } /** * #param $arg * #return string * #throws Exception */ public function hdateConvert($arg): string { if ($arg instanceof \DateTime) { $dayNumber = $arg->format('N'); $arg->modify('+1 day'); $year = $arg->format('Y'); $month = $arg->format('n'); $day = $arg->format('j'); $dayH = [ "الأثنين", "الثلاثاء", "الأربعاء", "الخميس", "الجمعة", "السبت", "الأحد" ]; return $dayH[$dayNumber - 1] . " " . HdateExtension::Greg2Hijri($day, $month, $year); } throw new Exception('Invalid date'); } /** * #return string */ public function getName(): string { return 'hdate_extension'; } /** * #param int $day * #param int $month * #param int $year * #return string */ public function Greg2Hijri(int $day, int $month, int $year): string { if ( ($year > 1582) or (($year == 1582) and ($month > 10)) or (($year == 1582) and ($month == 10) and ($day > 14)) ) { $jd = HdateExtension::intPart((1461 * ($year + 4800 + HdateExtension::intPart(($month - 14) / 12))) / 4) + HdateExtension::intPart((367 * ($month - 2 - 12 * (HdateExtension::intPart(($month - 14) / 12)))) / 12) - HdateExtension::intPart((3 * (HdateExtension::intPart(($year + 4900 + HdateExtension::intPart(($month - 14) / 12)) / 100))) / 4) + $day - 32075; } else { $jd = 367 * $year - HdateExtension::intPart((7 * ($year + 5001 + HdateExtension::intPart(($month - 9) / 7))) / 4) + HdateExtension::intPart((275 * $month) / 9) + $day + 1729777; } $l = $jd - 1948440 + 10632; $n = HdateExtension::intPart(($l - 1) / 10631); $l = $l - 10631 * $n + 354; $j = (HdateExtension::intPart((10985 - $l) / 5316)) * (HdateExtension::intPart((50 * $l) / 17719)) + (HdateExtension::intPart($l / 5670)) * (HdateExtension::intPart((43 * $l) / 15238)); $l = $l - (HdateExtension::intPart((30 - $j) / 15)) * (HdateExtension::intPart((17719 * $j) / 50)) - (HdateExtension::intPart($j / 16)) * (HdateExtension::intPart((15238 * $j) / 43)) + 29; $month = HdateExtension::intPart((24 * $l) / 709); $day = $l - HdateExtension::intPart((709 * $month) / 24); $year = 30 * $n + $j - 30; $mname = [ "محرّم", "صفر", "ربيع الأوّل", " ربيع الثاني", "جمادى الأولى", "جمادى الثانية", "رجب", "شعبان", "رمضان", "شوّال", "ذو القعدة", "ذو الحجّة" ]; return "{$day} {$mname[$month - 1]} {$year} هـ "; } /** * #param $float * #return false|float */ private function intPart($float) { if ($float < -0.0000001) return ceil($float - 0.0000001); else return floor($float + 0.0000001); } }
Filling in PDF from web form in PHP
I have a form which on posting submits data to a controller which should then fill necessary fields and present form to users to physically sign before submitting back. I used Dhek https://github.com/cchantep/dhek do define the fields on which the form data will be placed and FPDF to generate the final PDF for downloading. I am able to get selected checkboxes marked but no text fields are rendered. Here is what I have tried so far $json = json_decode(file_get_contents($this->getRequest()->getUriForPath('/bundles/app/form.json'))); $responses = $request->query->all(); $pdfSrcPath = $this->container->getParameter('write_to') . '/bundles/app/Membership_App__form.pdf'; $pdf = new \FPDF_FPDI("P", //L=>Landscape / P=>Portrait "pt" /* point */ ); $fontSize = 14; $pagecount = $pdf->setSourceFile($pdfSrcPath); $testText = "abcdefghijklmnopqrstuvwxyz0123456789"; for ($i = 0; $i < $pagecount; $i++) { $pdf->AddPage(); $tplIdx = $pdf->importPage($i + 1); $pdf->useTemplate($tplIdx, 0, 0, 0, 0, true); if (isset($json->pages[$i]) && isset($json->pages[$i]->areas)) { for ($j = 0; $j < count($json->pages[$i]->areas); $j++) { $area = $json->pages[$i]->areas[$j]; $x = $area->x; $y = $area->y; $w = $area->width; $h = $area->height; // Draw blue rect at bounds $pdf->SetDrawColor(0, 0, 255); $pdf->SetLineWidth(0.2835); $pdf->Rect($x, $y, $w, $h); if ($area->type == "checkbox" && $area->name == $responses['title']) { $pdf->SetDrawColor(105, 105, 105); $pdf->SetLineWidth(2.0); $pdf->Line($x, $y, $x + $w, $y + $h); $pdf->Line($x, $y + $h, $x + $w, $y); } else if ($area->type == "text") { // 'Free' text $pdf->SetLineWidth(1.0); // border $iw = $w - 2 /* 2 x 1 */ ; $v = utf8_decode($responses[$area->name]); $overflow = ($pdf->GetStringWidth($v) > $iw); while ($pdf->GetStringWidth($v) > $iw) { $v = substr($v, 0, -1); } if ($overflow) { $v = substr($v, 0, -1) . "\\"; } $pdf->SetXY($x, $y); // this line is not rendering // tried $pdf->Write(intval($h),$v); // and also tried $pdf->Cell($w, intval($h), $v); $pdf->MultiCell($w, intval($h), $v, true); } } } } $pdf->Output("test-dhek.pdf", "F");
Calculate percentage saved between two numbers?
I have two numbers, the first, is the original price, the second, is the discounted price. I need to work out what percentage a user saves if they purchase at the second price. example 25, 10 = 60% 365, 165 = 55% What I dont know is the formula to calculate this.
I know this is fairly old but I figured this was as good as any to put this. I found a post from yahoo with a good explanation: Let's say you have two numbers, 40 and 30. 30/40*100 = 75. So 30 is 75% of 40. 40/30*100 = 133. So 40 is 133% of 30. The percentage increase from 30 to 40 is: (40-30)/30 * 100 = 33% The percentage decrease from 40 to 30 is: (40-30)/40 * 100 = 25%. These calculations hold true whatever your two numbers. Original Post
((list price - actual price) / (list price)) * 100% For example: ((25 - 10) / 25) * 100% = 60%
I see that this is a very old question, but this is how I calculate the percentage difference between 2 numbers: (1 - (oldNumber / newNumber)) * 100 So, the percentage difference from 30 to 40 is: (1 - (30/40)) * 100 = +25% (meaning, increase by 25%) The percentage difference from 40 to 30 is: (1 - (40/30)) * 100 = -33.33% (meaning, decrease by 33%) In php, I use a function like this: function calculatePercentage($oldFigure, $newFigure) { if (($oldFigure != 0) && ($newFigure != 0)) { $percentChange = (1 - $oldFigure / $newFigure) * 100; } else { $percentChange = null; } return $percentChange; }
The formula would be (original - discounted)/original. i.e. (365-165)/365 = 0.5479...
function calculatePercentage($oldFigure, $newFigure) { $percentChange = (($oldFigure - $newFigure) / $oldFigure) * 100; return round(abs($percentChange)); }
100% - discounted price / full price
If total no is: 200 and getting 50 number then take percentage of 50 in 200 is: (50/200)*100 = 25%
I have done the same percentage calculator for one of my app where we need to show the percentage saved if you choose a "Yearly Plan" over the "Monthly Plan". It helps you to save a specific amount of money in the given period. I have used it for the subscriptions. Monthly paid for a year - 2028 Yearly paid one time - 1699 1699 is a 16.22% decrease of 2028. Formula: Percentage of decrease = |2028 - 1699|/2028 = 329/2028 = 0.1622 = 16.22% Code: func calculatePercentage(monthly: Double, yearly: Double) -> Double { let totalMonthlyInYear = monthly * 12 let result = ((totalMonthlyInYear-yearly)/totalMonthlyInYear)*100 print("percentage is -",result) return result.rounded(toPlaces: 0) } Usage: let savingsPercentage = self.calculatePercentage(monthly: Double( monthlyProduct.price), yearly: Double(annualProduct.price)) self.btnPlanDiscount.setTitle("Save \(Int(savingsPercentage))%",for: .normal) The extension usage for rounding up the percentage over the Double: extension Double { /// Rounds the double to decimal places value func rounded(toPlaces places:Int) -> Double { let divisor = pow(10.0, Double(places)) return (self * divisor).rounded() / divisor } } I have attached the image for understanding the same:
This is function with inverted option It will return: 'change' - string that you can use for css class in your template 'result' - plain result 'formatted' - formatted result function getPercentageChange( $oldNumber , $newNumber , $format = true , $invert = false ){ $value = $newNumber - $oldNumber; $change = ''; $sign = ''; $result = 0.00; if ( $invert ) { if ( $value > 0 ) { // going UP $change = 'up'; $sign = '+'; if ( $oldNumber > 0 ) { $result = ($newNumber / $oldNumber) * 100; } else { $result = 100.00; } }elseif ( $value < 0 ) { // going DOWN $change = 'down'; //$value = abs($value); $result = ($oldNumber / $newNumber) * 100; $result = abs($result); $sign = '-'; }else { // no changes } }else{ if ( $newNumber > $oldNumber ) { // increase $change = 'up'; if ( $oldNumber > 0 ) { $result = ( ( $newNumber / $oldNumber ) - 1 )* 100; }else{ $result = 100.00; } $sign = '+'; }elseif ( $oldNumber > $newNumber ) { // decrease $change = 'down'; if ( $oldNumber > 0 ) { $result = ( ( $newNumber / $oldNumber ) - 1 )* 100; } else { $result = 100.00; } $sign = '-'; }else{ // no change } $result = abs($result); } $result_formatted = number_format($result, 2); if ( $invert ) { if ( $change == 'up' ) { $change = 'down'; }elseif ( $change == 'down' ) { $change = 'up'; }else{ // } if ( $sign == '+' ) { $sign = '-'; }elseif ( $sign == '-' ) { $sign = '+'; }else{ // } } if ( $format ) { $formatted = '<span class="going '.$change.'">'.$sign.''.$result_formatted.' %</span>'; } else{ $formatted = $result_formatted; } return array( 'change' => $change , 'result' => $result , 'formatted' => $formatted ); }
I think this covers this formula sufficiently, ((curr value - base value) / (curr value)) * 100% Basically we just (in programming): perform the calculation if both numbers are not 0. If curr value is 0 then we return -100 % difference from the base, if both are 0 then return 0 (we can't divide by 0) Powershell example: Strip any non numeric from vars and perform calculation Function Get-PercentageSaved { #((curr value - base value) / (curr value)) * 100% param( [Parameter(Mandatory = $false)][string]$CurrVal = $null, [Parameter(Mandatory = $false)][string]$BaseVal = $null ) $Result = $null Try { $CurrVal = [float]($CurrVal -replace '[^0-9.]', '') $BaseVal = [float]($BaseVal -replace '[^0-9.]', '') if (-Not($null -eq $CurrVal) -And (-Not($null -eq $BaseVal))) { if ($CurrVal -eq 0) { If ($BaseVal -eq 0) { $Result = 0 } Else { $Result = -100 } } else { $Result = [math]::Round([float]((($CurrVal - $BaseVal) / $CurrVal) * 100),2) } } } Catch {} Return [float]$Result }