2017-03-20

JavaScript 浮點數計算

一直一來都很少處理 JS 精準運算的問題,大部分的時候 UI 有點不準也不會造成太大的問題,這次用 JS 做一些加減的數字計算,遇到小數的時候就出現運算誤差,既然是 JS 計算機不精準是不行的,User 不可能接受的,找了一堆文章後沒一個靠譜的,但重點都是轉換到整數進行運算,再做浮點位移,整個計算最好盡量避免小數的處理,另外的問題就是位數不能太多。


function transformInt(num1, num2, padZeno, compute) {
    num1 = '' + num1;
    num2 = '' + num2;

    var p1 = 0, p2 = 0;
    try { p1 = num1.split(".")[1].length } catch (e) { }
    try { p2 = num2.split(".")[1].length } catch (e) { }

    if(padZeno){
        while (p1 < p2) { p1++; num1 += '0'; }
        while (p2 < p1) { p2++; num2 += '0'; }
    }

    var int1 = parseInt(num1.replace(".", ""), 10);
    var int2 = parseInt(num2.replace(".", ""), 10);
    return compute(int1, int2, p1, p2);
}


/*浮點數相加*/
function floatAdd(num1, num2) {
    return transformInt(num1, num2, true, function(int1, int2, p1, p2){
        return (int1 + int2) / Math.pow(10, p1);
    });
}

/*浮點數相減*/
function floatSub(num1, num2) {
    return transformInt(num1, num2, true, function(int1, int2, p1, p2){
        return (int1 - int2) / Math.pow(10, p1);
    });
}

/*浮點數相乘*/
function floatMul(num1, num2) {
    return transformInt(num1, num2, false, function(int1, int2, p1, p2){
        return (int1 * int2) / Math.pow(10, p1 + p2);
    });
}

/*浮點數相除*/
function floatDiv(num1, num2) {
    return transformInt(num1, num2, false, function(int1, int2, p1, p2){
        return (int1 / int2) / Math.pow(10, p1 - p2);
    });
}



function unitTest(method, list){
    console.log('=[ ' + method.name + ' ]==============================================');

    for (var i = 0; i < list.length; i++){
        var row = list[i];
        var result = method(row.num1, row.num2);

        if(result == row.ans){
            console.log(row, result);
        }else{
            console.error(row, result);
        }
    };
}

unitTest(floatAdd, [
    {num1:0.11, num2:0.2, ans: 0.31},
    {num1:0.21, num2:0.2, ans: 0.41},
    {num1:0.31, num2:0.2, ans: 0.51},
    {num1:0.41, num2:0.2, ans: 0.61},
    {num1:0.51, num2:0.2, ans: 0.71},
    {num1:0.61, num2:0.2, ans: 0.81},
    {num1:0.71, num2:0.2, ans: 0.91},
    {num1:0.81, num2:0.2, ans: 1.01},
    {num1:0.91, num2:0.2, ans: 1.11},
    {num1:1.01, num2:0.2, ans: 1.21},
]);

unitTest(floatSub, [
    {num1:1.02, num2:0.2, ans: 0.82},
    {num1:1.12, num2:0.2, ans: 0.92},
    {num1:1.22, num2:0.2, ans: 1.02},
    {num1:1.32, num2:0.2, ans: 1.12},
    {num1:1.42, num2:0.2, ans: 1.22},
    {num1:1.52, num2:0.2, ans: 1.32},
    {num1:1.62, num2:0.2, ans: 1.42},
    {num1:1.72, num2:0.2, ans: 1.52},
    {num1:1.82, num2:0.2, ans: 1.62},
    {num1:1.92, num2:0.2, ans: 1.72},
]);

unitTest(floatMul, [
    {num1:10, num2:0.14, ans: 1.4},
    {num1:10, num2:0.24, ans: 2.4},
    {num1:10, num2:0.34, ans: 3.4},
    {num1:10, num2:0.44, ans: 4.4},
    {num1:10, num2:0.54, ans: 5.4},
    {num1:10, num2:0.64, ans: 6.4},
    {num1:10, num2:0.74, ans: 7.4},
    {num1:10, num2:0.84, ans: 8.4},
    {num1:10, num2:0.94, ans: 9.4},
    {num1:10, num2:1.04, ans: 10.4},
]);

unitTest(floatDiv, [
    {num1:1.1, num2:0.1, ans: 11},
    {num1:1.1, num2:0.2, ans: 5.5},
    {num1:0.99, num2:0.3, ans: 3.3},
    {num1:1.1, num2:0.4, ans: 2.75},
    {num1:1.1, num2:0.5, ans: 2.2},
    {num1:1.32, num2:0.6, ans: 2.2},
    {num1:1.54, num2:0.7, ans: 2.2},
    {num1:1.76, num2:0.8, ans: 2.2},
    {num1:2.97, num2:0.9, ans: 3.3},
    {num1:1.1, num2:0.1, ans: 11},
]);

2016-04-07

C# MVC + Cassette

Cassette 與 MVC 預設的 Bundle 最大的差異就是會自動轉換 CSS 的圖片網址。缺點就是開發時 F5 啟動專案會變慢。


NuGet 安裝

  • Cassette.Aspnet
  • Cassette.Views
  • Cassette


Web.config


基本上安裝完就會自動配置以下設定,但可以在確認一下。

<configuration>
  <configSections>
    <section name="cassette"
             type="Cassette.CassetteConfigurationSection, Cassette"
             requirePermission="false"
    />
  </configSections>
  <system.web>
    <pages>
      <namespaces>
        <add namespace="Cassette.Views" />
      </namespaces>
    </pages>
    <httpModules>
      <add name="CassetteHttpModule"
           type="Cassette.Aspnet.CassetteHttpModule, Cassette.Aspnet"
      />
    </httpModules>
    <httpHandlers>
      <!-- 用來處理綑綁打包的處理器 -->
      <add path="cassette.axd"
           verb="*"
           type="Cassette.Aspnet.CassetteHttpHandler, Cassette.Aspnet"
       />
    </httpHandlers>
  </system.web>
  <system.webServer>
    <!-- 保留 httpHandlers(IIS6) 及 handlers(IIS7) 需要關閉驗證 -->
    <validation validateIntegratedModeConfiguration="false" />
    <modules>
      <add name="CassetteHttpModule"
           type="Cassette.Aspnet.CassetteHttpModule, Cassette.Aspnet"
      />
    </modules>
    <handlers>
      <!-- 用來處理綑綁打包的處理器 -->
      <add name="CassetteHttpHandler"
           path="cassette.axd"
           verb="*"
           allowPathInfo="true"
           preCondition="integratedMode"
           type="Cassette.Aspnet.CassetteHttpHandler, Cassette.Aspnet"
       />
    </handlers>
  </system.webServer>

  <!-- For configuration options: http://getcassette.net/documentation/v2/web-config -->
  <cassette rewriteHtml="false" />
</configuration>



Views/Web.config


增加給 cshtml 用的 namespace

<configuration>
  <system.web.webPages.razor>
    <pages pageBaseType="System.Web.Mvc.WebViewPage">
      <namespaces>
        <add namespace="Cassette.Views" />
      </namespaces>
    </pages>
  </system.web.webPages.razor>
</configuration>



CassetteConfiguration.cs


public class CassetteBundleConfiguration : IConfiguration<BundleCollection>
{
    public void Configure(BundleCollection bundles)
    {
        bundles.AddPerIndividualFile<StylesheetBundle>("Content");
        bundles.AddPerIndividualFile<ScriptBundle>("Scripts");

        bundles.Add<StylesheetBundle>("Styles/Bundles", new string[] 
        {
            "~/Scripts/bootstrap/css/bootstrap.css",
            "~/Scripts/bootstrap/css/bootstrap-theme.css",
            //...
        });

        bundles.Add<ScriptBundle>("Scripts/Bundles", new string[] 
        {
            "~/Scripts/jquery/jquery-1.12.2.js",
            "~/Scripts/jquery.validate/jquery.validate-1.12.0.js",
            //...
        });
    }
}



_Layout.cshtml


<!DOCTYPE html>
@{
    Bundles.Reference("Styles/Bundles");
    Bundles.Reference("Scripts/Bundles");
}
<html>
<head>
    @Bundles.RenderStylesheets()
</head>
<body id="DialogLayout">
    @Bundles.RenderScripts()
</body>
</html>



Release Mode


當 Web.config 的 compilation debug="false" 就會壓縮綑綁。

<compilation debug="false" targetFramework="4.5" />
2015-11-26

天文鐘

2015-10-23

[PHP] 從 RGB 轉換到 HSB

HSB(HSV)通過色相/飽和度/亮度三要素來表達顏色。
  • H(Hue):表示颜色的類型 (例如红色,绿色或者黄色),取值範圍為 0 ~ 360,其中每一个值代表一種顏色
  • S(Saturation):顏色的飽和度從 0 到 1,有时候也稱為纯度 (0 表示灰度圖,1 表示纯的顏色)
  • B(Brightness or Value):顏色的明亮程度從 0 到 1 (0 表示黑色,1 表示特定飽和度的顏色)

function rgb2hsb($rgb) {
    $red   = max(0, min(255, $rgb['red']));
    $green = max(0, min(255, $rgb['green']));
    $blue  = max(0, min(255, $rgb['blue']));

    $max = max($red, $green, $blue);
    $min = min($red, $green, $blue);
    $delta = $max - $min;

    $b = $max / 255;
    $s = $max == 0 ? 0 : $delta / $max;

    $h = 0;
    if ($delta == 0) {
        $h = 0;
    } else if ($max == $red && $green >= $blue) {
        $h = 0   + 60 * ($green - $blue) / $delta;
    } else if ($max == $red && $green < $blue) {
        $h = 360 + 60 * ($green - $blue) / $delta;
    } else if ($max == $green) {
        $h = 120 + 60 * ($blue - $red) / $delta;
    } else if ($max == $blue) {
        $h = 240 + 60 * ($red - $green) / $delta;
    }

    return array('hue' => fmod($h, 360), 'saturation' => $s, 'brightness' => $b);
}



function hsb2rgb($hsb) {
    $h = $hsb['hue'];
    $s = max(0, min(1, $hsb['saturation']));
    $b = max(0, min(1, $hsb['brightness']));

    $h = fmod($h, 360);
    if($h < 0){ $h += 360; }

    $i = ($h / 60) % 6;
    $f = ($h / 60) - $i;
    $p = $b * (1 - $s);
    $q = $b * (1 - $f * $s);
    $t = $b * (1 - (1 - $f) * $s);

    $p = intval(round(255 * $p));  
    $q = intval(round(255 * $q));
    $t = intval(round(255 * $t));
    $b = intval(round(255 * $bri));
    
    switch ($i) {
        case 0: return array('red' => $b, 'green' => $t, 'blue' => $p);
        case 1: return array('red' => $q, 'green' => $b, 'blue' => $p);
        case 2: return array('red' => $p, 'green' => $b, 'blue' => $t);
        case 3: return array('red' => $p, 'green' => $q, 'blue' => $b);
        case 4: return array('red' => $t, 'green' => $p, 'blue' => $b);
        case 5: return array('red' => $b, 'green' => $p, 'blue' => $q);
        default: return array('red' => 0, 'green' => 0, 'blue' => 0);
    }
}

[PHP] 從 Hex 轉換到 RGB

function hex2rgb($hex) {
    list($r, $g, $b) = sscanf($hex, "%02x%02x%02x");
    return array('red' => $r, 'green' => $g, 'blue' => $b);
}

function rgb2hex($rgb) {
    return sprintf("%02x%02x%02x", $rgb['red'], $rgb['green'], $rgb['blue']);
}